My understanding of TCP connection is that a source PORT remains exclusive to one connection, no matter the destination is, so the number of connections from local port 12345 for example can never exceed 1.
I recently read that a TCP connection is identified by <src IP, src PORT, dst IP, dst PORT>
TCP allows source port sharing across multiple processes, but each process requires a free port to bind to for its connection
so I went to validate that "port sharing across processes": this must mean that the same source port can be used to connect to different destinations.
However, when experimenting this, I tried these two commands:
nc -v -p 12345 google.com 80
which works well (-v for verbose, and -p to specify the source port as 12345, for my learning purpose)
Now, simultaneously running this command on a different shell
nc -v -p 12345 github.com 80
fails with this error message:
nc: connectx to github.com port 80 (tcp) failed: Address already in use
the reason I specified the same source port with -p is to validate that a source port can be shared. There's no need for this practically, in real-world scenario I would not even worry about source port. According to this, is it true that a source port will be only used once?
There is no reason why two processes cannot use the same source port, as long as they do not both connect to the same destination (host, port). On many UNIX systems, set the
SO_REUSEPORT
option to enable processes to share a port number; on Windows, setSO_REUSEADDR
. For example, withsocat
:socat stdio tcp:google.com:80,bind=:12345,reuseport
socat stdio tcp:bing.com:80,bind=:12345,reuseport
These two processes can run simultaneously, and will both have source port 12345 (as you can confirm with
netstat
).Note, however, that you will almost certainly run into issues if the sockets are not closed cleanly on both ends, as unclosed TCP sockets will enter a
TIME_WAIT
state which will cause the four-tuple (srcaddr, srcport, dstaddr, dstport) to be tied up until the wait period expires. Therefore, when using a single source port for multiple connections, you cannot reconnect to the exact same server & port unless the previous connection has fully shut down or theTIME_WAIT
period has expired.Any port is only ever allocated to a single process at any point in time. That process can create any number of connections with it, with the restriction that the destination IP address or port number must vary between connections.
As an example, TCP 10.0.0.10:49152 can connect only once to TCP 10.0.0.2:80 but can at the same time connect to TCP 10.0.0.3:80 or TCP 10.0.0.2:8080.
While the TCP protocol itself allows arbitrary combinations of local and remote ports and addresses, most Unix implementations simplify port management. The reason is that the process of setting up sockets is split into separate steps.
First you set the local port with
bind()
. This step is required when creating a listening TCP socket (you have to specify what port it's listening on), it's optional before making an outgoing connection withconnect()
(an arbitrary local port will be assigned). Since we don't know the remote address or port yet, it's not possible to tell whether this is fully unique. So it simply checks whether the requested port is available. If the socket has theSO_REUSEADDR
option set, it ignores connected sockets when checking whether the local address is in use, but it will still fail if there's a listening socket on the port.Then for an outgoing connection you call
connect()
, specifying the remote address. You can only callconnect()
once on a socket, and because we checked the local port duringbind()
, this can never produce a duplicate local/remote address/port.For an incoming connection, you call
accept()
on the listening socket. Again, because we check that the local port of the listening socket is unused when we bind it, there can never be a duplicate combination.Delaying the port checks until we have the remote information would complicate error handling. The current design just checks for duplication in one place:
bind()
.After some investigations I found that source port sharing is only allowed for multiple outgoing connections from the same process. The operating system needs to know which process to forward the connection stream to.
Going to select this answer in two days as the site policy.