イントラネット内の異なるホストで実行されている複数のプロセスを使用する Windows (Microsoft Visual C++ 2005) アプリケーションで作業しています。
プロセスは、TCP/IP を使用して相互に通信します。異なるプロセスは、同じホスト上または異なるホスト上にあります (つまり、通信は同じホスト内または異なるホスト間で行うことができます)。
現在、不定期に発生するバグがあります。通信はしばらく機能しているように見えますが、その後機能しなくなります。その後、しばらくすると再び機能します。
通信が機能しない場合、エラーが発生します (明らかに、プロセスがデータを送信しようとしている間)。呼び出しは次のようになります。
send(socket, (char *) data, (int) data_size, 0);
取得したエラーコードを調べることで
WSAGetLastError()
エラー 10054 であることがわかります。これは、Microsoft のドキュメントで見つけたものです (こちらを参照)。
WSAECONNRESET
10054
Connection reset by peer.
An existing connection was forcibly closed by the remote host. This normally
results if the peer application on the remote host is suddenly stopped, the
host is rebooted, the host or remote network interface is disabled, or the
remote host uses a hard close (see setsockopt for more information on the
SO_LINGER option on the remote socket). This error may also result if a
connection was broken due to keep-alive activity detecting a failure while
one or more operations are in progress. Operations that were in progress
fail with WSAENETRESET. Subsequent operations fail with WSAECONNRESET.
したがって、私が理解している限り、接続は受信プロセスによって中断されました。場合によっては、このエラーは (私の知る限り) 正しいものです。1 つのプロセスが終了したため、到達できません。それ以外の場合、送信側と受信側の両方が実行され、アクティビティをログに記録していますが、上記のエラーが原因で通信できません (エラーはログに報告されます)。
私の質問。
- SO_LINGER オプションの意味は何ですか?
- キープアライブ アクティビティとは何ですか? また、どのように接続を切断することができますか?
- この問題を回避または回復するにはどうすればよいですか?
最後の質問について。私たちが最初に試した解決策 (実際には回避策です) は、エラーが発生したときにメッセージを再送信することでした。残念ながら、しばらくの間(数分間)同じエラーが何度も発生します。したがって、これは解決策ではありません。
現時点では、ソフトウェアに問題があるのか、構成に問題があるのかわかりません。Windows レジストリで何かを確認する必要があるのではないでしょうか?
1 つの仮説は、OS がエフェメラル ポートを使い果たす (接続が閉じられているが、TcpTimedWaitDelay のためにポートが解放されていない場合) というものでしたが、この問題を分析することで、多くのポートがあるはずだと考えています。プロセス間で頻繁に送信されます。ただし、これを除外できるかどうかはまだ 100% 確信が持てません: エフェメラル ポートが何らかの方法で失われる可能性はありますか (???)
役立つかもしれないもう 1 つの詳細は、送信と受信が別々のスレッドで同時に各プロセスで発生することです。TCP/IP ライブラリに破損する可能性のある共有データ構造はありますか?
非常に奇妙なのは、問題が不規則に発生することです。通信は数分間正常に機能し、その後数分間機能しなくなり、その後再び機能します。
アイデアや提案をありがとう。
編集
考えられる唯一の説明が接続の閉じられたエラーであることを確認するヒントをありがとう。問題をさらに分析したところ、接続のサーバー側プロセスがクラッシュしたか、終了して再起動されたことがわかりました。そのため、新しいサーバー プロセスが実行され、正しいポートでリッスンしていましたが、クライアントはこれを検出せず、まだ古い接続を使用しようとしていました。このような状況を検出し、クライアント側で接続をリセットするメカニズムが用意されました。