10245


[RFC793
に書かれている状態遷移図](http://www.atmarkit.co.jp/ait/articles/0402/13/news096_3.html)（原文では[§3.2](https://www.rfc-
editor.org/rfc/rfc793#section-3.2)のFigure6）では、サーバー側は LISTEN ... ESTABLISHED
... CLOSED と遷移していくように書かれています。

リモートエンドポイントを指定せずに LISTEN 状態に入ったサーバーは、クライアントからの接続を受けてリモートエンドポイントを確定し、 ESTABLISH
状態に入ります。 **しかしその後もサーバーは他のエンドポイントからの接続を待ち受けています。**

この流れは「 LISTEN 状態のソケットが1つあり、接続を受けると ESTABLISHED
に遷移する」では説明がつかないように思うのですが、どのように考えるとよいのでしょうか？


CC BY-SA 3.0
2015-05-16T00:58:06.910
10243
2015-05-16T06:29:59.837
2021-10-07T07:34:52.683
-1
8000
question
tcp network
TCPサーバーはLISTEN状態のソケット一つでどうやって複数の接続を捌くのでしょうか？


> この流れは「 LISTEN 状態のソケットが1つあり、接続を受けると ESTABLISHED  
>  に遷移する」では説明がつかないように思うのですが、どのように考えるとよいのでしょうか？

「コネクション」と「ソケット」の区別をしてください。  
その状態遷移図は「コネクション」の状態を示しているもので、「ソケット」の状態ではありません。

§1.5. Operation

> Concatenated with the network and host addresses from the internet  
>  communication layer, this forms a socket. A pair of sockets uniquely  
>  identifies each connection.

§2.7. Connection Establishment and Clearing

> A local socket may participate in many connections to different  
>  foreign sockets.

ひと組のソケット（つまりローカルのソケットとリモートのソケット）によってコネクションを識別しています。  
ソケットが1つであっても、コネクションが1つであるとは限りません。1つのソケットが複数のコネクションに紐付けられていてもよいのです。


CC BY-SA 3.0
2015-05-16T02:25:10.940
10245
2015-05-16T02:25:10.940
3639
10243
answer


  1. サーバプロセスは listen(2) で接続準備をカーネルに指示します。
  2. その際、backlog で何個の接続待ちキューを作るかを指示します。たとえば 5 が指定されれば、5 個までの同時接続を受け付けることが可能です。
  3. カーネルが１個の接続を受け付けると、5 個のうちの一つが SYN_RECEIVED を経て ESTABLISHED になります。ただし、他の 4 つの接続待ちキューの状態は相変わらず LISTEN のままです。

このように、１つのセッションでは無理でも、サーバホスト単位では ESTABLISHED と LISTEN が同時に共存可能ということになります。


CC BY-SA 3.0
2015-05-16T02:32:27.463
10246
2015-05-16T06:29:59.837
2015-05-16T06:29:59.837
1046
1046
10243
answer


ざっくり言うと、仕様と矛盾しない範囲で工夫して実装されているということですよね。

> しかしその後もサーバーは他のエンドポイントからの接続を待ち受けています。

そもそも、RFC 793 で言及されている TCP のユーザインタフェースは、BSD Socket API
を想定したものではなく、以下のような単純なものです。

  * OPEN
  * SEND
  * RECEIVE
  * CLOSE

RFC に記載されている TCP コネクションの状態遷移図に記載されているイベントも、このインタフェース（コマンド）の通りですよね。

> この流れは「 LISTEN 状態のソケットが1つあり、接続を受けると ESTABLISHED に遷移する」では説明がつかないように思うのですが

RFC 記載のユーザインタフェースには、BSD Scoket API の listen() -> accept()
に相当するものはありませんので、説明がつかないのは当然といえば当然ですね。

実際には、h2so5 さんが回答されているように `ローカルソケットは複数の外部からのソケットに参加することができる`
と記載されていますので、その前提をもとに考えると listen() したソケットが accept() した後に再度接続を待ち受けるという動きは RFC
と矛盾していないというのが分かると思います。


CC BY-SA 3.0
2015-05-16T02:50:42.463
10247
2015-05-16T03:02:07.017
2015-05-16T03:02:07.017
1024
1024
10243
answer