1. ホーム
  2. networking

[解決済み] ソケットAPIのaccept()関数はどのように動作するのですか?

2022-06-13 06:02:29

質問

ソケットAPIは、TCP/IPおよびUDP/IP通信のデファクトスタンダードです(つまり、私たちが知っているネットワークコードです)。しかし、その中心的な機能の 1 つである accept() は少し不思議です。

半官半民の定義を借りると

accept() はサーバーサイドで使用されます。 からの新しいTCP接続を作成するために、受信した着信の試行を受け取ります。 から新しい TCP 接続を作成するために受信した試みを受け入れ を受信し、そのソケットに関連付けられた新しい ソケットを作成します。 アドレスのペアに関連付けられた新しいソケットを作成します。

言い換えると accept は新しいソケットを返し、それを通してサーバーは新しく接続されたクライアントと通信することができます。古いソケット(その上で accept が呼び出された)古いソケットは、同じポートで開かれたまま、新しい接続を待ちます。

どのようにして accept はどのように機能するのでしょうか?どのように実装されているのでしょうか?このトピックには多くの混乱があります。多くの人は、accept が新しいポートを開き、それを通してクライアントと通信すると主張します。しかし、新しいポートは開かれないので、これは明らかに真実ではありません。実際には、同じポートを通じて異なるクライアントと通信することができます。複数のスレッドが recv を呼び出した場合、データはどこに行くかをどのように知るのでしょうか?

クライアントのアドレスがソケットディスクリプタに関連付けられ、データが送られてくるたびに recv を介してデータが来るたびに、正しいソケットにルーティングされるのだと思いますが、よくわかりません。

この仕組みの内部を徹底的に解説してもらえると助かります。

どのように解決するのですか?

あなたの混乱は、ソケットがサーバーIPとサーバーポートによって識別されると考えていることにあります。 実際には、ソケットは4つの情報によって一意に識別されます。

Client IP : Client Port そして Server IP : Server Port

したがって、サーバー IP とサーバー ポートは、受け入れたすべての接続で一定ですが、クライアント側の情報は、すべてがどこに向かっているのかを追跡することを可能にするものです。

物事を明確にするための例

にサーバがあるとします。 192.168.1.1:80 と二つのクライアントがあるとします。 10.0.0.110.0.0.2 .

10.0.0.1 ローカルポートで接続を開く 1234 で接続を開き、サーバに接続する。 これで、サーバーには次のように識別されるソケットが1つできました。

10.0.0.1:1234 - 192.168.1.1:80  

現在 10.0.0.2 はローカルポートで接続を開始します。 5678 で接続を開き、サーバに接続する。 これで、サーバーは以下のように識別された2つのソケットを持つことになります。

10.0.0.1:1234 - 192.168.1.1:80  
10.0.0.2:5678 - 192.168.1.1:80