2010-12-04 81 views
0

我創建了一個線程在阻塞套接字上接收,它會等到包到達。但是,當我嘗試從主線程斷開連接時,會在導致錯誤的線程之間發生競爭條件。多線程 - 斷開TCP連接

這裏交換髮生在線程之間的線程之間,沒有實際完成斷開連接調用。

void Disconnect() { 
    if(isConnected) { 
     if (closesocket(sockClient) != SOCKET_ERROR) { 
      isConnected = false; 
     } 
    } 
} 

我該如何避免切換並優雅地讓它完成斷開連接呼叫?

回答

1

這裏有兩種可能的解決方案。

您可以隔離套接字(非主)線程中的所有套接字訪問,而不是從主線程斷開套接字,而是讓該線程指示需要斷開連接(或其他某個動作)的非主線程。這將需要你的輔助線程等待兩個對象 - 套接字和一個信號器(例如Win32 Event),這表明需要斷開連接。

另一方面,如果您希望允許主線程斷開連接(就像您現在所做的那樣),您需要檢查所有使用該套接字的代碼,並使用鎖保護程序使其成爲線程安全的,以確保併發訪問套接字和相關的狀態數據被阻止。 Boost.Thread有合適的鎖,你可以在這裏使用,否則你可以在Win32 CriticalSection之類的東西上實現你自己的封裝。

第二個將是我的首選解決方案 - 事實上,您提出這個問題意味着您需要回頭考慮設計中的線程安全性。即使你按照上面的第一個想法走,你仍然可能需要保持狀態以避免從主線程發送多個斷開連接信號,並且必須鎖定守衛。此外,如果您希望非主線程處理除「斷開連接」之外的傳入事件,則會有線程間必須管理的關聯狀態。

我認爲你現在所在位置的阻力最小的路徑是將鎖定添加到現有的代碼中。確保您的鎖定範圍儘可能窄 - 例如,不要設置任何可能阻塞或需要很長時間的套接字調用所持有的鎖定。

+0

在輔助線程中,我有一個無盡的while循環調用receive()來檢查消息,並在那個接收調用中有一個阻塞recv()等待消息。我如何在插座上等待時發出信號? – user963241 2010-12-04 17:28:19