0

私は最近、いくつかのサーバークライアントコードに取り組んでいましserverたが、非常に紛らわしい問題を発見しました。connect

man、気付きました

The backlog parameter defines the maximum length for the queue of pending
 connections.  If a connection request arrives with the queue full, the
 client may receive an error with an indication of ECONNREFUSED.  Alterna-
 tively, if the underlying protocol supports retransmission, the request
 may be ignored so that retries may succeed.

これは、クライアント接続が失敗するか、後で再試行することを意味します。

しかし、私のクライアントが実行されているとき、それは単に SIGPIPE シグナルを受け取り、失敗しました。

だから私は実行sudo tcpdump -ilo0 port 10000して結果を得る:

summertekiMacBook-Pro: summer$ sudo tcpdump -ilo0 port 10000 を選択

tcpdump: 詳細な出力を抑制、lo0 でリッスンする完全なプロトコル デコードに -v または -vv を使用、リンク タイプ NULL (BSD ループバック)、キャプチャ サイズ 65535 バイト

10:29:16.396240 IP localhost.56347 > localhost.ndmp: フラグ [S]、seq 3366561899、win 65535、オプション [mss 16344、nop、wscale 4、nop、nop、TS val 396158772 ecr 0、sackOK、eol]、長さ 0

10:29:16.396241 IP localhost.56349 > localhost.ndmp: フラグ [S]、seq 902832276、win 65535、オプション [mss 16344、nop、wscale 4、nop、nop、TS val 396158772 ecr 0、sackOK、eol]、長さ 0

10:29:16.396242 IP localhost.56351 > localhost.ndmp: フラグ [S]、seq 1956535575、win 65535、オプション [mss 16344、nop、wscale 4、nop、nop、TS val 396158772 ecr 0、sackOK、eol]、長さ 0

10:29:16.396244 IP localhost.56348 > localhost.ndmp: フラグ [S]、seq 2161003109、win 65535、オプション [mss 16344、nop、wscale 4、nop、nop、TS val 396158772 ecr 0、sackOK、eol]、長さ 0

10:29:16.396246 IP localhost.56350 > localhost.ndmp: フラグ [S]、seq 1318035540、win 65535、オプション [mss 16344、nop、wscale 4、nop、nop、TS val 396158772 ecr 0、sackOK、eol]、長さ 0

10:29:16.396296 IP localhost.ndmp > localhost.56347: フラグ [S.]、seq 2871094527、ack 3366561900、win 65535、オプション [mss 16344、nop、wscale 4、nop、nop、TS val 396158772 ecrOK 396158772、s ,eol]、長さ 0

10:29:16.396307 IP localhost.ndmp > localhost.56351: フラグ [S.]、seq 3931313020、ack 1956535576、win 65535、オプション [mss 16344、nop、wscale 4、nop、nop、TS val 396158772 ecrOK 396158772、s ,eol]、長さ 0

10:29:16.396332 IP localhost.ndmp > localhost.56349: フラグ [S.]、seq 3467781056、ack 902832277、win 65535、オプション [mss 16344、nop、wscale 4、nop、nop、TS val 396158772 ecrOK 396158772、s ,eol]、長さ 0

10:29:16.396349 IP localhost.ndmp > localhost.56348: フラグ [S.]、seq 2666080832、ack 2161003110、win 65535、オプション [mss 16344、nop、wscale 4、nop、nop、TS val 396158772 eckOK 396158772、s ,eol]、長さ 0

10:29:16.396366 IP localhost.ndmp > localhost.56350: フラグ [S.]、seq 2467582351、ack 1318035541、win 65535、オプション [mss 16344、nop、wscale 4、nop、nop、TS val 396158772 ecrOK 396158772、s ,eol]、長さ 0

10:29:16.396375 IP localhost.56347 > localhost.ndmp: フラグ [.]、ack 1、win 9186、オプション [nop、nop、TS val 396158772 ecr 396158772]、長さ 0

10:29:16.396381 IP localhost.56351 > localhost.ndmp: フラグ [.]、ack 1、win 9186、オプション [nop、nop、TS val 396158772 ecr 396158772]、長さ 0

10:29:16.396386 IP localhost.56349 > localhost.ndmp: フラグ [.]、ack 1、win 9186、オプション [nop、nop、TS val 396158772 ecr 396158772]、長さ 0

10:29:16.396391 IP localhost.56348 > localhost.ndmp: フラグ [.]、ack 1、win 9186、オプション [nop、nop、TS val 396158772 ecr 396158772]、長さ 0

10:29:16.396398 IP localhost.56350 > localhost.ndmp: フラグ [.]、ack 1、win 9186、オプション [nop、nop、TS val 396158772 ecr 396158772]、長さ 0

10:29:16.396408 IP localhost.ndmp > localhost.56347: フラグ [R]、seq 2871094528、win 0、長さ 0

10:29:16.396413 IP localhost.ndmp > localhost.56351: フラグ [R]、シーケンス 3931313021、勝利 0、長さ 0

10:29:16.396419 IP localhost.56347 > localhost.ndmp: フラグ [P.]、seq 1:1001、ack 1、win 9186、オプション [nop、nop、TS val 396158772 ecr 396158772]、長さ 1000

10:29:16.396424 IP localhost.56351 > localhost.ndmp: フラグ [P.]、seq 1:1001、ack 1、win 9186、オプション [nop、nop、TS val 396158772 ecr 396158772]、長さ 1000

10:29:16.396429 IP localhost.ndmp > localhost.56349: フラグ [.]、ack 1、win 9186、オプション [nop、nop、TS val 396158772 ecr 396158772]、長さ 0 10:29:16.396435 IP localhost.ndmp > localhost.56348: フラグ [R]、seq 2666080833、勝利 0、長さ 0

10:29:16.396441 IP localhost.ndmp > localhost.56350: フラグ [.]、ack 1、win 9186、オプション [nop、nop、TS val 396158772 ecr 396158772]、長さ 0

10:29:16.396454 IP localhost.ndmp > localhost.56347: フラグ [R]、seq 2871094528、win 0、長さ 0

10:29:16.396460 IP localhost.ndmp > localhost.56351: フラグ [R]、シーケンス 3931313021、勝利 0、長さ 0

UNIX ネットワーク プログラミングから、3 回のハンドシェイク ルーチンconnect()を開始し、サーバーがsyn && ackを送信すると戻ります。

出力から、上位 10 行は、バックログtcpdumpが 2 であるにもかかわらず、サーバーが syn & sck を返信したことを示しています。その後、クライアントは前回の ackを送信し、サーバーは rst を返します。

私の意見では、connect return with value != -1 は、接続が確立され、クライアントがデータを送信できることを意味します。しかし、上記のログは、そのようには機能しないことを示しています。

誰でもどちらが正しいか教えてもらえますか?

4

2 に答える 2

0

壊れた/閉じたパイプでデータを送信しようとすると、SIGPIPE シグナルを受け取ります。あなたのtcpdumpデータによると、あなたが説明したように:

  • 5 つの TCP 接続はすべて、5 つの異なるクライアント ポート (56347 ~ 56351) から (3 ウェイ ハンドシェイクで) 正しく確立されます。
  • 次に、サーバーはポート 47 および 51 からの接続でリセットを送信します。これにより、パイプが切断されます。
  • ほぼ同時に、データがポート 47 および 51 (クライアント内) からサーバーに送信 ([P]、プッシュ) されます。おそらく、このデータはすでにソケット送信バッファーにあり、カーネルが決定したときに送信する準備ができています。その後、サーバーは Reset [R] で再び応答しますが、これは何も変更しません。
  • 実際、tcpdump の最後の 4 行は、この説明には影響しません。

connect は実際にクライアント プログラムで OK を返しました。すべての接続が正常に確立され、3 ウェイ ハンドシェイクが完了したからだと思います。問題は、その後すぐにデータを送信しようとすることです。各ソケットで複数回データを送信しようとしているに違いありません。各スレッドが 1 つのソケットを処理すると仮定します。スレッドがポート 56347 または 56351 を使用してソケット上でデータを送信しようとする 2 回目または 3 回目 (またはそれ以上) の場合、サーバーから既に受信した RESET のためにパイプが壊れ、OS はシグナル SIGPIPE をプロセスに送信します。

listen backlog は、サーバーで正常に動作しているようです。3 つの接続が正しく処理され、2 つだけが拒否されたようです。おそらく、サーバーは最初の接続を十分に高速に処理して、バックログで次の 2 つの接続の場所を空けたのでしょう。最後の 2 つは、バックログが小さすぎるため、達成できませんでした (2)。

于 2013-10-28T19:41:01.880 に答える