3

バックグラウンド:

TCPを介して接続する別々のマシン上の複数のクライアントを備えた1台のマシンでTCPサーバーを実行しており、Wiresharkを使用して、サーバーアプリケーション内から、およびSystem.NetのSystem.Diagnosticstracelistenerを介してログを記録してネットワークトラフィックを監視しています。 。冗長モードのソケット。

問題:

予期しない切断が発生したためにログを調べるように求められましたが、非常に奇妙な動作が見られます。サーバーアプリケーションログとSystem.Diagnostic出力ログによると、サーバーは開始/終了送信を使用して4バイトのパケットをクライアントに送信しています。BeginSendが完了し、EndSendも4バイトのパケットを正常に送信したことを示して完了します。

ただし、Wiresharkのログを見ると、そのパケットは表示されません。サーバーマシンでWiresharkを実行しているので、パケットがサーバーとトレースログに表示される理由はありませんが、同じマシンのWiresharkログには表示されません。

また、パケット送信が成功したと思われる直後(約30秒後)に予期しない切断が発生します。これは、サーバーのEndReceiveメソッドのSocketExceptionが原因で発生します。しかし、サーバーからの送信が試行されるまでの間に、サーバーはクライアントから受信したパケットを確認しているので、接続がまだアクティブであることがわかります。

誰かが同様の経験をしたことがありますか、またはこれを引き起こしている可能性のあるバグや何かを知っていますか?

これがソケットレベルで発生しているとは考えたくありません。TCPは、パケットがネットワークに到達しなかったときに送信されると言っています。つまり、信頼できるトランスポートとしてTCPに依存することはできません(もちろん、 TCPの要点です)。

ログサンプル

私のサーバーアプリケーションから:

    2011-09-07 10:41:38,812 Attempting to send Packet (BeginSend - 4 bytes)
    2011-09-07 10:41:38,812 Sent Packet (EndSend - 4 bytes)

System.Diagnosticsトレースログから:

System.Net.Sockets Verbose: 0 : [4376] Socket#19699911::BeginSend()
    DateTime=2011-09-07T17:41:38.8125000Z
System.Net.Sockets Verbose: 0 : [0980] Data from Socket#19699911::PostCompletion
    DateTime=2011-09-07T17:41:38.8125000Z
System.Net.Sockets Verbose: 0 : [0980] 00000000 : 02 04 00 00                                     : ....
    DateTime=2011-09-07T17:41:38.8125000Z
System.Net.Sockets Verbose: 0 : [4376] Socket#19699911::EndSend(OverlappedAsyncResult#44209720)
    DateTime=2011-09-07T17:41:38.8125000Z
System.Net.Sockets Verbose: 0 : [4376] Exiting Socket#19699911::EndSend()   -> 4#4
    DateTime=2011-09-07T17:41:38.8125000Z
System.Net.Sockets Verbose: 0 : [4376] Exiting Socket#19699911::BeginSend()     -> OverlappedAsyncResult#44209720
    DateTime=2011-09-07T17:41:38.8125000Z

Wiresharkのログも貼り付けますが、クライアントからのパケットとサーバーからの対応する確認応答を除いて、基本的にその時点でそのデバイスのインターフェイスに登録されているものはありません。

編集: 要求に応じて、ここに送信のコードがあります(スペースなどの理由で短縮されています)。非常に単純で、問題が発生する可能性のあるものの邪魔になることはあまりありません。

私のBeginSendメソッドでは:

socket.BeginSend(data, 0, data.Length, SocketFlags.None, EndSend, state);

私のEndSendメソッドでは:

bytesSent = socket.EndSend(ar);

注:彼らが言うように、これは私の最初のロデオではありません...私は過去15年間、TCPソケットを使用してサーバーとクライアントを作成してきましたが、これまで経験したことはありません。

また、私が使用している.NETのバージョンは4.0です...それが関連性がある場合。

ヘルプ!

4

4 に答える 4

0

その制限を無視できるのであれば、アプリケーションを書き直してTcpClient代わりに使用することは可能Socketでしょうか? とにかく、アプリが TCP/IP にバインドされている場合は、少なくともこの特定のソケットについては、抽象化を使用することもできます-それは役立つかもしれません. また、EndSend(IAsyncResult, SocketError)オーバーロードを使用して、SocketErrorオブジェクトに有用なものが含まれているかどうかを確認することもできます。

これらのソフトウェアの微調整のいずれも役に立たない場合、問題は .NET ソフトウェア レベル以下、つまりファイアウォール ソフトウェア (またはハードウェア)、ウイルス対策などにあることに同意する必要があります。

于 2011-09-07T20:12:22.057 に答える
0

この質問は何年も前のことなので、おそらく先に進んでいるでしょう... 他の誰かが同じ問題を抱えている場合に備えて、Windows のメモリ プレッシャ プロテクションが作動しているかどうかを確認することをお勧めします。これにより、次の場合にパケットがドロップされます。複数の同時接続があり、それがあなたが見ているものです。

別の実験として、サーバー マシンのファイアウォールを一時的にオフにすることもできます。これにより、これらの保護メカニズムもすべてオフになり (私の間違いでなければ)、問題が解決すれば、そのうちの 1 つが原因であることがわかります。

于 2013-09-03T02:42:09.670 に答える
0

.NET でのソケット プログラミングで遭遇した 1 つの問題は、ガベージ コレクションに関連していました。私のコードはソケットを作成し、メンバ変数に代入する代わりにメソッド内のローカル変数に代入していました。その後、ソケットがガベージ コレクションされ、SocketException. どうやら、BeginSendそのソケットへの参照を保持するには、 a を実行するだけでは不十分でした。

ソケットをメンバー変数に移動すると、問題が解決しました。うまくいけば、これはあなたが遭遇している問題に関連しています。

于 2011-09-07T20:01:17.333 に答える
0

これがソケット レベルで発生しているとは考えたくありません。TCP は、パケットがネットワーク上に到達していないにもかかわらず送信されたと言っています。これは、TCP を信頼できるトランスポートとして信頼できないことを意味します (もちろん、これはもちろんです)。が TCP の要点です)。

このステートメントは正しくありません。ソケットへの書き込みに成功したからといって、データがクライアントによって受信された、またはマシンから離れたことを意味するわけではありません。これは、内部 TCP/IP バッファに正常に書き込まれたことを意味します。TCP/IP は、適切と思われる数または数のブロック/フレームでそのデータを送信します。これは特に、送信するデータが小さい場合に当てはまります。TCP/IP は、追加のデータをフレームに集約しようとして遅延します。

Wireshark で表示されない場合は、適切なインターフェイスでリッスンしていないか、フィルタが設定されているか、何らかのファイアウォールによってデータの送信が妨げられている可能性があります。ウイルス対策サービスやその他のレイヤー サービス プロバイダーを調べて、誰が侵入しているのかを確認してください。

于 2011-09-07T20:06:03.950 に答える