1

これは私がソケットを閉じる方法です:

LINGER lingerStruct;
lingerStruct.l_onoff = 1;
lingerStruct.l_linger = 0;
setsockopt(Clients[iClientID].ClientSocket, SOL_SOCKET, SO_LINGER, (char*)&lingerStruct, sizeof(lingerStruct));
CancelIo((HANDLE)Clients[iClientID].ClientSocket);
shutdown(Clients[iClientID].ClientSocket, SD_BOTH);
closesocket(Clients[iClientID].ClientSocket); // << Hangs here

約 2 ~ 10 時間の実行時間の後、500 を超えるソケットを閉じた後、ランダムなソケットが閉じられず、closesocket() がクリティカル セクションで永久にハングすることが起こります (デバッガーを使用してこれを見つけました)。

私は何を間違っていますか?

コンパイラ: Visual Studio 2010 SP1 (C++) OS: Windows Server 2008 R2 x64

ありがとう。

4

2 に答える 2

1

CancelIo 関数は同期的ではありません。少なくとも、同期的であることが保証されているとは文書化されていません。そのソケットの I/O が保留中の場合は、I/O がキャンセルされたことを確認する完了通知を受け取るまで待機する必要があります (または、キャンセル要求がキューに入れられる前に正常に完了した可能性があります)。

完了通知を受け取ったら、ソケットを安全に閉じられるはずです。

于 2012-11-07T09:16:13.000 に答える
0
LINGER lingerStruct;
lingerStruct.l_onoff = 1;
lingerStruct.l_linger = 0;
setsockopt(Clients[iClientID].ClientSocket, SOL_SOCKET, SO_LINGER, (char*)&lingerStruct, sizeof(lingerStruct));

それをすべて取り除きます。それはあなたにとってもピアにとっても何の役にも立ちません。呼び出しclosesocket()て、TCP をデフォルト モードで動作させるだけです。それとも、故意にデータの損失とピアでのリセットを引き起こそうとしていますか? もしそうなら、なぜですか?

CancelIo((HANDLE)Clients[iClientID].ClientSocket);

私もそれを取り除きたいと思うでしょう。ソケットを閉じると、私が考えていたすべての処理が行われるはずですが、私は非同期 I/O の専門家ではありません。あなたはそれを試すことができます。

shutdown(Clients[iClientID].ClientSocket, SD_BOTH);

それを取り除きます。前は冗長closesocket()です。

于 2012-11-07T06:05:28.753 に答える