Dev Learning Lab

The labs on this site need JavaScript to run. The same content is written out below.

Learn › Networking › Transport layer

Sockets and ports

Of the several programs on one computer, which one receives this data?

An IP address leads only to one computer. Which of the programs running on that computer receives the data is decided by the port number. A program creates a socket and binds it to a port number, and the operating system passes data that arrives for that port to that socket. This lab shows which program a connection reaches, depending on the ports the servers listen on and the port the client connects to.

Checked against real execution · The 27 combinations were run on 127.0.0.1 with the net module of Node.js 24 and checked against the results

Concepts in this lab

Port
A port is a number from 0 to 65535 that tells apart which of the several programs running on one computer should receive the data. If an IP address points to the computer, a port points to the program inside that computer, so the place to connect to is written as "IP address:port". A server program waits for connections on a port it has chosen, and some numbers are widely agreed upon, such as 80 (HTTP) and 443 (HTTPS) for web servers. Normally only one program can wait for connections on a port, so starting a server on a port that is already in use causes an "address already in use" error. The ports of TCP and the ports of UDP are managed separately, so the same number in each is a different thing.
Socket
A socket is the endpoint of communication that a program uses to send and receive data over a network, and the operating system creates it and hands it to the program. The program only writes to and reads from the socket, and the operating system does the actual work of splitting up, sending, and receiving the data. One TCP connection consists of a pair of sockets, one at each end, and the operating system tells connections apart by four values: the source IP address, the source port, the destination IP address, and the destination port. This is why a server can receive connections from several clients at once on a single port, with a separate socket created for each connection. If you do not close a socket after using it, the resources of the operating system stay tied up.
Ephemeral port
An ephemeral port is the source port number that the operating system chooses automatically when a client connects to a server. The client code writes only the port of the other side (the server), and the operating system lends a free number for its own side. When the connection ends, the number is given back and can be used again for another connection. The range from which numbers are picked depends on the operating system and its settings, so you must not assume that a particular number will come up. If a very large number of new connections are made in a short time, there may be no numbers left to lend, and a new connection can fail.
TCP and UDP
The two main ways of transporting data on the internet. TCP establishes a connection before communication, guarantees that data arrives complete and in order, and sends data again if there is a problem. UDP sends data without a connection and does not guarantee arrival or order, but in return it is lightweight and fast. HTTP/1.1, HTTP/2, and database connections use TCP, and real-time video and voice and DNS mainly use UDP.

Try these

Running with the default settings

  1. serverA.listen(9000): Server A creates a socket, binds it to port 9000, and registers with the operating system: "Give the connections that arrive on port 9000 to this socket." Port 9000 was free, so this succeeds. Server A now waits for connections.
  2. serverB.listen(9000): Server B also tries to register port 9000. Server A is already using it, so the operating system refuses, and Server B receives an EADDRINUSE (address already in use) error. Only one program can receive the connections that arrive on a port, because otherwise the operating system could not decide whom to give them to.
  3. Client 1 calls net.connect(9000): The code gives only the destination port. The operating system picks one of the free numbers (here 50001) as the source port. Server A is listening on port 9000, so the connection is established.
  4. Client 2 calls net.connect(9000): This time the operating system picks 50002 as the source port. Server A is listening, so the connection is established. The destination port is the same 9000 as in the earlier connection, and only the source port differs. The operating system treats connections as different if even one of the four values (source IP, source port, destination IP, destination port) differs.
  5. Client 3 calls net.connect(9000): This time the operating system picks 50003 as the source port. Server A is listening, so the connection is established. The destination port is the same 9000 as in the earlier connection, and only the source port differs. The earlier two connections are not closed and stay open.
  6. socket.write: Each of the 3 clients sends its data. All of it goes to port 9000, but the operating system looks at the source port to tell which connection the data belongs to, and passes it to Server A separately for each connection, because each connection has its own socket.

Result of this run

Code

// Node.js (net module). Both the servers and the clients run on this computer (127.0.0.1)
const net = require('net');

const serverA = net.createServer(conn => conn.on('data', d => conn.write('A')));
serverA.listen(9000, '127.0.0.1');             // start listening on port 9000

const serverB = net.createServer(conn => conn.on('data', d => conn.write('B')));
serverB.on('error', e => console.log(e.code));  // if it fails, the error name is printed
serverB.listen(9000, '127.0.0.1');             // the port that Server A already uses

for (let i = 1; i <= 3; i++) {
  const socket = net.connect(9000, '127.0.0.1');   // write only the destination port. The source port is not written
  socket.on('connect', () => {
    console.log(socket.localPort);              // the source port chosen by the operating system
    socket.write('c' + i);
  });
  socket.on('data', d => console.log(d.toString()));   // which server received it
  socket.on('error', e => console.log(e.code));
}

Assumptions of this model

The 27 combinations were actually run with the net module on 127.0.0.1 of the PC used to write this lab (Windows, Node.js 24) and checked against the results. What was checked: the result of the listen call of Server B (success or EADDRINUSE), the number of successful and refused client connections (ECONNREFUSED), the server that received the data, the number of connections the server saw, whether the ports of the server-side sockets were all the same as the one listening port, and whether the client-side ports were different from each other. In the runs, three ports that were free at the time were used instead of 9000, 9001, and 9002, and because the client-side port numbers (such as 50001 on the screen) change on every run, only the fact that they are "different from each other" was used as a result. The range from which an operating system picks ephemeral ports depends on the operating system and its settings (the range that IANA recommends is 49152 to 65535, Section 6 of RFC 6335). That a connection is identified by the IP addresses and ports on both sides is the definition in the TCP specification (the entries for connection and socket in the glossary in Section 4 of RFC 9293). Not covered: clients on another computer, and special socket options (such as SO_REUSEPORT) that let several programs share the same port.

Previous lab: Switches and routers · Next lab: TCP connections and retransmission

Concepts in this lab

What this lab shows

Settings

Code


      
    

Diagram

Run comparison

Try these