ソケットAPIのaccept()関数はどのように機能しますか?


126

ソケットAPIは、TCP / IPおよびUDP / IP通信(つまり、私たちが知っているネットワークコード)の事実上の標準です。ただし、そのコア機能の1つは、accept()少し不思議です。

セミフォーマルな定義を借用するには:

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

つまり、acceptサーバーが新しく接続されたクライアントと通信できる新しいソケットを返します。(accept呼び出された)古いソケットは開いたままで、同じポートで新しい接続をリッスンします。

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

それは、ソケット記述子に関連付けられているクライアントのアドレスの行に沿ったものだと思います。データがrecvそれを通過するときはいつでも、正しいソケットにルーティングされますが、よくわかりません。

このメカニズムの内部の仕組みについて徹底的に説明していただければ幸いです。


2
そのため、すべてのクライアント要求に対して、サーバー側の真新しいソケット接続が開かれます。着信コールをリッスンするには、サーバーが常に80で開いている必要があります。呼び出しを受信すると、次に示すように、4つのタプルを持つ新しいソケットをすぐに作成し、クライアントとサーバー間でTCP接続を確立します。私の理解は正しいですか?
ブレインストーム

1
これは非常に基本的な質問で、最近インタビューでテストされました:stackoverflow.com/questions/24871827/…これについてコメントがある場合は投稿してください
ブレインストーム

@brainstorm HTTPキープアライブの存在を完全に無視する場合のみ。
ローン侯爵

回答:


140

混乱は、ソケットがサーバーIP:サーバーポートで識別されると考えることにあります。実際には、ソケットはカルテットの情報によって一意に識別されます。

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

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

明確にするための例:

たとえば192.168.1.1:80、1つのサーバーと2つのクライアントがある10.0.0.1とし10.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

3
実装の詳細(プラットフォームごとに異なる可能性があります)はわかりません。概念的には、ソケットは、私が説明した4組の情報によって識別されることを知っています。

3
これについて何か言及はありますか?
10

3
ランダムな質問:NATが使用されており、同じネットワーク上の2つのクライアントがサーバーに接続するときに同じローカルポートを使用しようとするとどうなりますか?たとえば、10.0.0.1と10.0.0.2の両方が外部IP 192.168.0.1のルーターに接続されている場合、192.168.1.1のサーバーは192.168.0.1からの2つの接続を認識します。その場合、乱数ジェネレータの変則によって10.0.0.1と10.0.0.2の両方が同じローカルポートを選択するとどうなりますか?
aroth

4
ルーターのNATサポートは、そこでの詳細を処理します。ネットワークトラフィックは、実際には2つの接続(クライアントからルーター、およびルーターからサーバー)を経由します。ルータは、2つの異なるポート192.168.0.1:1234および192.168.0.1:5678で発信接続を確立します。着信トラフィックは、ルーターによって正しいクライアントにリダイレクトされます。
26年

3
ソケットがカルテットで識別される場合、リスニングソケットのカルテット情報とは何ですか?
Eric Zheng

74

ユーザーからの回答「17 of 26」に追加するだけです

ソケットは実際には5つのタプルで構成されています-(ソースIP、ソースポート、宛先IP、宛先ポート、プロトコル)。ここで、プロトコルはTCPまたはUDPまたは任意のトランスポート層プロトコルである可能性があります。このプロトコルは、IPデータグラムの「プロトコル」フィールドのパケットで識別されます。

したがって、まったく同じ4タプルでプロトコルフィールドが異なる同じクライアントと通信するサーバー上の異なるアプリケーションを使用することができます。例えば

サーバー側のApache(TCP上のserver1.com:880-client1:1234)と(UDP上のserver1.com:880-client1:1234)上のWorld of Warcraft

他の4つのフィールドがすべて同じであっても、クライアントとサーバーの両方がこれをIPパケットのプロトコルフィールドとして処理するため、どちらの場合も異なります。


13

これを学んでいたときに私を混乱させたのは、用語が物理的なものであることsocketport示唆し、実際にはそれらがネットワーキングの詳細を抽象化するためにカーネルが使用する単なるデータ構造であるということでした。

したがって、データ構造は、異なるクライアントからの別々の接続を維持できるように実装されています。それらがどのように実装されるかについては、答えはa。)どちらでも構いません。ソケットAPIの目的は、実装が重要ではないこと、またはb。)見ているだけです。1つの実装の詳細な説明を提供する強く推奨されるStevensの本の他に、LinuxまたはSolarisまたはBSDの1つにあるソースを確認してください。


はい、ほとんどのネットワーキング用語は、ビットの特定のコレクションとその値(「プロトコル識別子」、「ルーティング」、「バインディング」、「ソケット」など)に基づいて行われる決定に名前を割り当てるだけです。ネットワークカードのハードウェアは、ビットのストリームを受信するように設計されています。コンピュータ上のプログラムに関連してそれらに何が起こるかは、ドライバとOSによって決定されます。必要に応じて、明日すべての用語を取り除くことができますが、ビットストリームを配信するという原則は基本的なようです...
masterxilo

-1

他の人が言ったように、ソケットは4タプル(クライアントIP、クライアントポート、サーバーIP、サーバーポート)によって一意に識別されます。

サーバーIPで実行されているサーバープロセスは、アクティブソケットのデータベース(どのようなテーブル/リスト/ツリー/アレイ/マジックデータ構造を使用するかは気にしません)を維持し、サーバーポートでリッスンします。(サーバーのTCP / IPスタックを介して)メッセージを受信すると、データベースに対してクライアントIPとポートをチェックします。クライアントIPとクライアントポートがデータベースエントリで見つかった場合、メッセージは既存のハンドラーに渡されます。それ以外の場合は、新しいデータベースエントリが作成され、そのソケットを処理するために新しいハンドラーが生成されます。

ARPAnetの初期の頃は、特定のプロトコル(FTPの1つ)は、指定されたポートで接続要求をリッスンし、ハンドオフポートで応答していました。その接続のためのさらなる通信はハンドオフポートを経由します。これは、パケットごとのパフォーマンスを向上させるために行われました。当時のコンピュータは、数桁も低速でした。


「ハンドオフポート」の部分について詳しく説明できますか?
Eli Bendersky、2009年

1
これは、一部のpre-TCPプロトコルの説明であるか、過度に簡略化されています。リスニングソケットに接続しようとするクライアントは、特別なパケットを送信して接続を確立します(SYNビットセット)。新しいソケットを作成するパケットと既存のソケットを使用するパケットには明確な違いがあります。
John M、

...特別なパケットを送信して接続を確立します(SYNビットセット)。これは(私が理解しているように)プロトコルスタックに「リスナー」(存在する場合)に渡させるため、アドレス/ポート/プロトコルの組み合わせごとに1つのリスニングポートしか存在できません。これが仕様にあるのか、単なる実装規約なのかはわかりません。
Peter Wone 2013

1
2番目の段落では、TCP層またはサーバープロセス内で発生することを正しく説明していません。サーバープロセスは、あらゆる種類のソケットのデータ構造を維持したり、受信したIP:ポートペアを何に対してもチェックしたりする必要はありません。それがソケットの目的です。FTPは、すべての「さらなる通信」ではなく、データ用に別のポートを使用し、パフォーマンス上の理由ではなく、プロトコルを簡素化するために行われます。新しいポートを使用する一方で、パフォーマンスはまったく向上しません。
ローン侯爵

「データベースを維持します(つまり、どの種類のテーブル/リスト/ツリー/配列/マジックデータ構造を使用するかを気にしません)」:)通常、これを「テーブル」(または「グラフ」または「決定木」)と呼びます)。「データベース」は私にいくつかの実装を示唆しています。
masterxilo 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.