TCPの回線接続について

はじめまして。TCPの勉強を始めたばかりです。
TCPの回線接続について、ご教示いただければ幸いです。

回線の接続時に、LANアナライザで見るところのSYN→SYN+ACK→ACKは
サーバー側がacceptしている状態で、クライアントがconnectを発行すると
やりとりされるパケットだと認識しているのですが、テストツールを使って
動かしてみると、違う結果が出てしまいます。

UNIX側でサーバーAPを実行し、WINDOWS側でクライアントAPを実行させました。

サーバー側では、接続待ちを5つまで許可する形でLISTENソケットを作りました。
このソケットは、開けっ放しの状態で待機しています。その後acceptを発行し、
クライアントからのconnectにより回線接続しました。
ここまでは良いのですが、その後、サーバーがaccept待ちをする前に
クライアントからconnectを行うと、SYN→SYN+ACK→ACKが出て、
2本目の回線が接続が出来てしまうのです。(forkも使っていないのです。)
但し、WINDOWサイズがやたらと小さいのです。

acceptされていなくても、接続が出来てしまうのでしょうか?
LISTENの待ち行列を5つにしているのが良くないのでしょうか?

色々な書籍を調べてみましたが、良く解らずにいてこのサイトを見つけました。
困ったときの神頼みでスミマセン。

名前: 
まりこ
日時: 
03/05/26 16:46

コメント

まりこさん,こんにちわ。

プログラマを引退して年月が経つので,記憶が風化している部分もありますが...

acceptの前でも,listenが完了していれば,ソケットの状態は接続待ちになるので,
その時点でSYNパケットを受け付けることはできるっていうことじゃないのかしら。
つまり,acceptは新しい接続に対応して作られるソケットを
アプリケーションに渡すために使うものなので,acceptしなくても,
listenするだけでソケットは接続可能な状態になるということだと思います。
そして,listenしたところにSYNが来たら,
SYN+ACK,ACKと続けて,接続動作を完了し,
接続したコネクション用に新しくソケットができ,
この新しくできたソケットのディスクリプタを受け取る動作がacceptだということで。

記憶が風化しているので,自信はないのですが,そんな感じだったと思います。
だから,このような事態が起こるんじゃないかしら。
間違っていたら,指摘してください。 > 皆様

それから,ソケットに対する操作はすべてディスクリプタによって識別するので,
ソケットに対する操作とプロセスをforkするかどうかは直接関係ないはずです。
forkしなくても,別のディスクリプタを使ってsocket,bind,listen,acceptすれば,
一つのプロセスで複数通信することも可能です。

この辺,詳しく知りたかったら,
デバガでプログラムをステップ実行しながら,
LANアナライザでパケットの動きを追いかけながら,
netstatでソケットの状態も随時見てみるとよいと思います。

早々のご返信ありがとうございます。

snoopとnetstatを使いながらやってみたのですが、
なんとなく、おっしゃっているとおりの動きのように見えました。
環境のあるところに行って、デバッカを使って止めながらやってみます。

それにしても解らないのが、最初につなげた回線をサーバー側でcloseして
再度acceptする間に接続要求が来ていても、
サーバーのアプリがacceptから復帰するまでに3秒程度かかるのです。
なんらかの設定値があるのでしょうか?
(こうなるとUNIXの範疇なのでしょうか…。ご存知でしたら教えてください。)

その間にRSTを受信していますが、RSTに対してはsocketをcloseする以外に
やれる事はないのですよね。この場合はFINが相手に送信されるのでしょうか?

また質問になってしまいました。すみません。
なんにせよ、デバッカを使ってみて結果をご報告致します。

>環境のあるところに行って、デバッカを使って止めながらやってみます。

デバガが使えなければ,キー入力待ちにして,
一つ一つ実行する方法もありますよ。

>それにしても解らないのが、最初につなげた回線をサーバー側でcloseして
>再度acceptする間に接続要求が来ていても、
>サーバーのアプリがacceptから復帰するまでに3秒程度かかるのです。
>なんらかの設定値があるのでしょうか?
>(こうなるとUNIXの範疇なのでしょうか…。ご存知でしたら教えてください。)

うーん,これはわからないです。
というか,コードを見てみればわかるのかもしれないのですが,
そこまではご勘弁ください。

>その間にRSTを受信していますが、RSTに対してはsocketをcloseする以外に
>やれる事はないのですよね。この場合はFINが相手に送信されるのでしょうか?

TCPの仕様では,FINに対してはACKで応答しますが,
RSTに対しては応答を返さないことになっていたと思います。

こんにちわ。

キー入力待ちにしてやってみました。
サーバー側でListenを発行後、acceptの前でキー入力待ちにしてみました。
クライアントから接続したら、スリーハンドシェイクが出て(snoopで確認)
接続が出来ていました。送信をしても特にエラーにはなりませんでした。
(当たり前な事にサーバーからのACK応答に付加されたウィンドウサイズは
 小さくなってはいましたが。)

要は、Listenの第二引数の許容数というのは、サーバーがacceptしてこなくても
クライアントから接続要求をいくつ出せるかという数なのですね。

サーバー側でacceptしなくては、回線は繋がらないと思っていたのは
間違いだったという事が解りました。

このような事を、直接詳しい方に尋ねる事ができるサイトがあって助かりました。
ありがとうございます。