8

In Chapter 4, paragraph 4.3 of Steven's "The Socket: Networking API, Third Edition", the author states the following

"If connect fails, the socket is no longer usable and must be closed. 
 We cannot call connect again on the socket."

Does anyone know the reason behind the above statement?

In my own experiments, i wrote a simple tcp client, that would run on host A and a simple tcp server, that would run on host B. The tcp client would attempt to connect to the tcp server on Host B forever.

So, i started the server on host B. Pulled the network wire from the host. Then i started the client on host A. After about 9 unsuccessful connect attempts on the same socket, i simply plugged the network wire back into the server host. The client connected successfully and happily sends messages at 80K/sec.

In yet another experiment, i pulled the wire from the server host, after a initial successful connect and few million messages exchanges after. Then, after few minutes, i connected the wire and message flow resumed on the same socket.

4

5 に答える 5

7

POSIX 2001、有益なセクションで次のように述べています。

失敗した場合connect()、ソケットの状態は未指定です。適合するアプリケーションは、再接続を試みる前に、ファイル記述子を閉じて新しいソケットを作成する必要があります。

したがって、あなたが引用した一節は、この仕様と一致しています。あなたのマシンで動作するという事実は、あなたのプログラムが移植可能であることを意味しません。

于 2012-10-28T15:08:54.677 に答える
2

これは、 connectのマンページに根ざしている可能性があります。

一般に、接続ベースのプロトコル ソケットが成功connect()するのは 1 回だけです。コネクションレス プロトコル ソケットは connect() 、関連付けを変更するために複数回使用される場合があります。

これは、接続ベースの (読み取り、TCP) ソケットを再接続できないことを意味します。connect()ただし、 FDをリサイクルできないことを意味する失敗について何も言っていないと思います。

接続が中断された場合に接続を再開することは、TCP の機能であり、通常はそれを試みます。

于 2012-10-28T15:06:39.537 に答える
1

以前と同じアドレスに接続しようとしている新しいソケットではなく、同じソケットを使用していますか?

これがあなたがしていることであっても、あなたが実験している特定の OS が接続に失敗したソケットの再利用を許可しているという事実は、ソケット API (または以前/以降のバージョン) を実装する他のすべての OS を意味するわけではありません。同じ OS の) も同様に寛容になるため、わずかに移植性のないコードを生成するリスクがあります。

API コントラクトで動作が約束されていないことを行うと、一般に何が起こるかわかりません。考えられる反応の 1 つは、お金を払っている顧客が自分のマシンでコードを実行しようとする瞬間まで、動作しているように見えるということです。

そのリスクはclose(socket); socket=socket(...);、かなりまれなエラー状況でのコストに見合うだけの価値がありますか?

于 2012-10-28T15:04:21.387 に答える
1

特定の質問に答えるには...

簡単に言うと、数多くの TCP 実装が存在します。connect()失敗した後に別の呼び出しを行うことをサポートするものもありますが、他のものは、そのようなことを信頼できないものにする状態情報を持っています。

reset()安全のために、ソケットを元の状態に戻す何らかの操作が必要です。これは元の (または後続の) TCP 実装には含まれていないため、残っている唯一のオプションは、閉じてから再度開くことです。

したがって、POSIX 標準 (およびおそらく POSIX 標準を参照として使用しているあなたの本) は、TCP/IP をサポートするすべてのオペレーティング システムで動作できるようにするために、まさにそれを行うように指示しています。そうしないと、いくつかの既存の実装が無効になります。

さらに、新しい実装では、試行が失敗した後に新しい接続を開始することを心配する必要がないため、自由に実装を簡素化できます。これにより、コードが少なくなり、バグが忍び寄る可能性が低くなります。

于 2012-10-29T17:56:17.140 に答える