How does the server find out what client port to send to

sockettcp

As I understand it this is what happens when a client makes a connection request:

  1. The server will be bound to a particular port number. The port number is always bound to a listening process. Since only the server is listening for incoming connections, we don't need to bind on the client side
  2. The server will keep on listeninig on that port number.
  3. The client will send a connect() request.
  4. The server will accept the request using accept(). As soon as the server accepts the client request, the kernel allocates a random port number for the server for further send() and receive(), since the same port number on the server can't be used for sending as well as listening, and the previous port is still listening for new connections

Given all that, how does the server find out what port the client is receiving on? I know the client will send TCP segments with a source port and destination port, so the server will use the source port of that segment as its destination port, but what function does the server call to find out about that port? Is it accept()?

Best Answer

It's part of the TCP (or UDP, etc.) header, in the packet. So the server finds out because the client tells it. This is similar to how it finds out the client's IP address (which is part of the IP header).

E.g., every TCP packet includes an IP header (with source IP, destination IP, and protocol [TCP], at least). Then there is a TCP header (with source and destination port, plus more).

When the kernel receives a SYN packet (the start of a TCP connection) with a remote IP of 10.11.12.13 (in the IP header) and a remote port of 12345 (in the TCP header), it then knows the remote IP and port. It sends back a SYN|ACK. If it gets an ACK back, the listen call returns a new socket, set up for that connection.

A TCP socket is uniquely identified by the four values (remote IP, local IP, remote port, local port). You can have multiple connections/sockets, as long as at least one of those differs.

Typically, the local port and local IP will be the same for all connections to a server process (e.g. all connections to sshd will be on local-ip:22). If one remote machine makes multiple connections, each one will use a different remote port. So everything but the remote port will be the same, but that's fine—only one of the four has to differ.

You can use, e.g., wirehsark to see the packet, and it'll label all the data for you. Here is the source port highlighted (notice it highlighted in the decoded packet, as well as the hex dump at the bottom):

Wireshark showing a TCP SYN packet

Related Question