2010-12-04 27 views
0

ブロッキングソケットで受信するスレッドを作成します。パケットが到着するまで待機します。しかし、プライマリスレッドから切断しようとすると、スレッド間で競合が発生し、エラーが発生します。マルチスレッド - TCP接続の切断

ここでは、実際に切断呼び出しを終了することなく、スレッド間の5行目で切り替えが行われます。

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

どのようにして、スイッチを回避し、優雅にそれが切断コールを終了させなければなりませんか?

答えて

1

ここには2つの解決策があります。

ソケット(プライマリではない)スレッドですべてのソケットアクセスを切り離すことができ、ソケットをプライマリスレッドから切断する代わりに、切断された(またはその他のアクション) 。これは、セカンダリスレッドがソケットと、切断が必要であることを示す署名者(Win32 Event)の2つのオブジェクトを待機する必要があります。

一方、プライマリスレッドの接続を切断したい場合は(現在のように)、ソケットを使用するすべてのコードをチェックし、ロックガードを使用してスレッドセーフな状態にして、ソケットおよび関連する状態データが防止される。 Boost.Threadには、ここで使用できる適切なロックがあります。そうしないと、Win32 CriticalSectionなどのラッパーとして自分自身を実装できます。

目は私の好み解決策になる - あなたがこの質問をしているという事実は、あなたが戻って、とにかくあなたのデザインのスレッドの安全性を考える必要がありますを意味します。上記の最初のアイデアを持っていても、複数の切断信号がプライマリスレッドから送信されるのを避けるためには、状態を維持する必要があり、ロックガードが必要です。また、プライマリ以外のスレッドが 'disconnect'以外の着信イベントを処理するようにしたい場合は、スレッド間で管理する必要のある関連状態が存在します。

私はあなたが今いる場所から最も抵抗の少ないパスが既存のコードにロックを追加することだと思います。可能な限り狭い範囲でロックを有効にするようにしてください。たとえば、ブロックするか、時間がかかるソケット呼び出しで保持しているロックを設定しないでください。ループがメッセージをチェックする()受信呼び出し中にセカンダリスレッドで

+0

は、私は無限をしましたし、その受信コールでメッセージを待ってブロッキングのrecv()があります。ソケットで待っている間、私はそれをどのように伝えますか? – user963241

+0

'WaitForSingleObject(terminateEvent)'にループを使用して、非同期受信を常にポストしておくことができます。私が指摘したように、これは2番目のアプローチがおそらくあなたにとって苦痛ではないもう一つの理由です。 –

+0

私が代わりにブール値をisConnectedのロックをチェックするために開始し、切り離しの終わり()、しばらく(のWaitForSingleObject(terminateEvent、0)== WAIT_TIMEOUT)でSetEvent()とResetEvent()を設定しました。それは動作しますが、私はあなたが本当に意味することを推測します。 – user963241

関連する問題