7

TCPソケットを介したクライアントサーバー通信をテストしています。サーバーをCで作成し、Linuxマシンで実行しており、ncテスト用のクライアントとして使用しています。

サーバーは、クライアントとの最初のメッセージ交換の後、応答を受け取らずに定期的にいくつかのメッセージをクライアントに送信します。

クライアントを強制終了するとsend()、サーバーによって最初に実行されたものがエラーで失敗する ことが予想されますが、これはクライアントが停止した後EPIPEの2番目でのみ判明します。send()私が殺した後の最初send()のクライアントは、1100バイトを(閉じていると思われる)ソケットに正常に送信できます。次のsend()操作は、実行されたとおりに終了しEPIPEます。

この振る舞いを説明してくれる人はいますか?TCP / IPスタックに書き込むので、可能な場合に配信するのはスタック次第であるという事実によるものですか?その場合、接続ステータスを確認するにはどうすればよいですか?ピアがまだそこにいることを確認します。

4

1 に答える 1

4

通常の TCP 接続は、4 ウェイ ハンドシェイクです。

http://en.wikipedia.org/wiki/Transmission_Control_Protocol

クライアントを強制終了すると、FINセグメントがクライアント側からサーバーに送信され、サーバー プロトコル スタックがACKを送信します。

ここで、サーバーがデータを読み取ろうとした場合、読み取り呼び出しは値 0 を返すため、サーバー プログラムはピアが閉じたことを認識でき、通常はその後接続ソケットを閉じます。これにより、サーバー側からのFINが送信され、クライアント側からの最後のACKの受信後に通常の 4 ウェイ ハンドシェイクが完了します。

( http://www.faqs.org/faqs/unix-faq/socket/の Q 2.1 をお読みください)

ただし、ここではサーバーからデータを書き込んでいるため、サーバーはデータを送信した後にのみクライアントからRESETを取得しています。そのため、2 番目の送信にある最初の送信操作の後にエラーが発生しています。

では、pl。サーバー側で send の最初の呼び出しでエラー (EPIPE とは異なる場合があります) を取得できるように、linger オプションとタイムアウトを 0 に設定して、4 ウェイ ハンドシェイクの代わりにクライアント側からの接続を突然閉じてみてください。 (これは推奨される方法ではありませんが、この特定のケースを理解するためだけのものです)

Try the following option of nc, nc -L 0 to set the linger option and timeout to 0

(私はncのこのオプションを試していません。このリンクで詳細を確認してくださいhttp://docs.oracle.com/cd/E23824_01/html/821-1461/nc-1.html

上記サイトのncの例、

Connect to TCP port, send some data and terminate the connection with 
TCP RST segment 
(instead of classic TCP closing handshake) by setting the linger option and 
timeout to 0:

$ echo "foo" | nc -L 0 host.example.com 22
于 2012-09-04T15:15:02.620 に答える