TCP: can two different sockets share a port?

This may be a very simple question, but it bothers me.

Can two different connected sockets share a port? I am writing an application server that should be able to handle more than 100 thousand. Parallel connections, and we know that the number of ports available in the system is about 60 thousand (16 bits). A connected socket is assigned to a new (dedicated) port, so this means that the number of concurrent connections is limited by the number of ports, if only several sockets cannot share the same port. So the question is.

Thanks for the help in advance!

+52
port sockets network-programming tcp
Jun 20 2018-12-12T00:
source share
4 answers

The socket server is listening on a single port. All established client connections on this server are connected to the same listening port on the server side . An established connection is uniquely identified by a combination of pairs of IP ports on the client side and server side. Several connections on the same server can share the same pair on the server side, if they are connected to different pairs of IP / ports on the client side , and the server can process as many clients as available system resources allow.

On the client side , a random client port is usually used for new outgoing connections, in which case you can run out of available ports if you earn a lot of connections in a short period of time.

+72
Jun 20 '12 at 23:32
source share

TCP / HTTP listening on ports: how many users can use the same port

So what happens when a server listens for incoming connections on a TCP port? For example, let's say you have a web server on port 80. Suppose your computer has a public IP address of 24.14.181.229, and the person trying to connect to you has an IP address of 10.1.2.3. This person can connect to you by opening a TCP socket up to 24.14.181.229:80. Simple enough.

Intuitively (and erroneously), most people think it looks something like this:

Local Computer | Remote Computer -------------------------------- <local_ip>:80 | <foreign_ip>:80 ^^ not actually what happens, but this is the conceptual model a lot of people have in mind. 

This is intuitive, because from the point of view of the client, it has an IP address and connects to the server via IP: PORT. Since the client connects to port 80, should its port also be 80? This is a reasonable thing to think about, but it’s not really what is happening. If this were correct, we could only serve one user to someone else's IP address. As soon as the remote computer connects, it will connect port 80 to port 80, and no one will be able to connect.

Three things to understand:

1.) On the server, the process is listening on the port. As soon as it receives the connection, it passes it to another thread. Communication never forces a listening port.

2.) Connections are uniquely identified by the OS with the following 5-tuple: (local-IP address, local port, remote IP protocol, remote port, protocol). If any element in the tuple is different, then this is a completely independent join.

3.) When the client connects to the server, it selects a random unused port of a high order source. Thus, one client can have up to ~ 64 thousand connections to the server for the same destination port.

So this is really what is created when the client connects to the server:

  Local Computer | Remote Computer | Role ----------------------------------------------------------- 0.0.0.0:80 | <none> | LISTENING 127.0.0.1:80 | 10.1.2.3:<random_port> | ESTABLISHED 

Looking at what is really going on

First, let me use netstat to see what is happening on this computer. We will use port 500 instead of 80 (because there are a whole bunch of things going on on port 80, since this is a common port, but functionally it does not matter).

  netstat -atnp | grep -i ":500 " 

As expected, the output is empty. Now start the web server:

  sudo python3 -m http.server 500 

Now here is the result of running netstat:

  Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN - 

So now there is one process that is actively listening (State: LISTEN) on port 500. The local address is 0.0.0.0, which is the code for "listening on all IP addresses." A simple mistake is to listen only on port 127.0.0.1, which will only accept connections from the current computer. Thus, this is not a connection, it just means that the process requested to bind () to the IP port, and this process is responsible for processing all connections to this port. This indicates a limitation that there can only be one process on a computer that listens on a port (there are ways to get around this using multiplexing, but this is a much more complicated topic). If the web server is listening on port 80, it cannot exchange this port with other web servers.

So now connect the user to our machine:

  quicknet -m tcp -t localhost:500 -p Test payload. 

This is a simple script ( https://github.com/grokit/quickweb ) that opens a TCP socket, sends a payload ("test load" in this case), waits a few seconds, and shuts down. The second execution of netstat is as follows:

  Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN - tcp 0 0 192.168.1.10:500 192.168.1.13:54240 ESTABLISHED - 

If you connect to another client and run netstat again, you will see the following:

  Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:500 0.0.0.0:* LISTEN - tcp 0 0 192.168.1.10:500 192.168.1.13:26813 ESTABLISHED - 

... that is, the client used another random port to connect. Thus, there is never any confusion between IP addresses.

+63
Nov 28 '14 at 5:45
source share

A connected socket is assigned to a new (dedicated) port

This is a common intuition, but it is not true. A connected connector is not assigned to a new / dedicated port. The only actual limitation that the TCP stack must satisfy is that the tuple (local_address, local_port, remote_address, remote_port) must be unique for each socket connection. Thus, a server can have many TCP sockets using the same local port if each of the sockets on the port is connected to a different remote location.

See the Socket Pair paragraph: http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA52&dq=socket%20pair%20tuple&pg=PA52#v=onepage&q=socket%20pair%20tuple&f=false

+17
Jun 20 2018-12-12T00:
source share
Theoretically, yes. No practice. Most kernels (including linux) do not allow you a second bind() for an already allocated port. This was not a really big patch to allow this.

Finally, we must distinguish between connector and port. Sockets are bidirectional communication endpoints, that is, “things” where we can send and receive bytes. This is a conceptual thing; there is no such field in the header of the package named "socket".

A port is an identifier that can identify a socket. In the case of TCP, the port is a 16-bit integer, but there are other protocols (for example, on Unix sockets, the "port" is essentially a string).

The main problem is this: if an incoming packet arrives, the kernel can determine its socket by its destination port number. This is the most common way, but this is not the only possibility:

  • Sockets can be identified by the destination IP address of incoming packets. This is the case, for example, if we have a server using two IPs at the same time. Then we can run, for example, different web servers on the same ports, but on different IP addresses.
  • Sockets can be identified by their source port and ip. This is the case in many load balancing configurations.

Since you are running an application server, he will be able to do this.

+1
Nov 07 '13 at 9:00
source share



All Articles