私が理解したところ、クライアントが接続要求をすると、次のことが起こります。
- サーバーは特定のポート番号にバインドされます。ポート番号は常に受信プロセスに関連付けられています。サーバーだけが着信接続を受信しているため、クライアント側でバインドする必要はありません。
- サーバーは引き続きこのポート番号をリッスンします。
connect()
クライアントが要求を送信します。- サーバーは承認要求を使用します
accept()
。サーバーがクライアント要求を受け入れると、カーネルは追加操作のためにサーバーにランダムなポート番号を割り当てます。これは、send()
サーバーreceive()
の同じポート番号が送受信に使用できず、古いポートがまだ新しい接続を受信しているためです。
これらすべてを考慮すると、サーバーはどのクライアントがどのポートでデータを受信しているかをどのように知ることができますか?クライアントは送信元ポートと宛先ポートを含むTCPセグメントを送信することを知っているので、サーバーはそのセグメントの送信元ポートを宛先ポートとして使用しますが、サーバーはどのポートを見つけるためにそのポートを見つけるのですか?うんaccept()
?
ベストアンサー1
これはパケットのTCP(またはUDPなど)ヘッダーの一部です。したがって、クライアントが指示するので、サーバーは調べます。これは、クライアントのIPアドレス(IPヘッダーの一部)を見つける方法と似ています。
たとえば、すべてのTCPパケットにはIPヘッダー(最小ソースIP、宛先IP、およびプロトコル[TCP]を含む)が含まれています。次にTCPヘッダー(ソースポートと宛先ポートなどを含む)が続きます。
カーネルがリモートIPが10.11.12.13(IPヘッダーから)でリモートポートが12345(TCPヘッダーから)のSYNパケット(TCP接続の開始)を受信すると、リモートIPとポートがわかります。 SYN | ACKを再送信します。 ACKが受信されると、listen
コールは接続に確立された新しいソケットを返します。
TCPソケットは、4つの値(リモートIP、ローカルIP、リモートポート、ローカルポート)で一意に識別されます。少なくとも1つが異なる限り、複数の接続/ソケットを持つことができます。
通常、ローカルポートとローカルIPは、サーバープロセスへのすべての接続に対して同じです(たとえば、sshdへのすべての接続はlocal-ip:22にあります)。リモートコンピュータが複数の接続を作成する場合、各接続は異なるリモートポートを使用します。したがって、リモートポート以外のすべては同じですが、大丈夫です。 4つのポートのうち1つだけが異なる必要があります。
たとえば、wirehsark を使用してパケットを表示でき、すべてのデータにタグが付けられます。以下は強調表示されたソースポートです(デコードされたパケットで強調表示され、下部の16進ダンプに注意してください)。