Dev Learning Lab

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

Learn › Networking › Transport layer

TCP and UDP

If you send data in three pieces, does it arrive in three pieces?

TCP and UDP are two ways of carrying the data of one program to another program. TCP first establishes a connection and delivers the bytes in order and without gaps, but it does not tell the receiver where the sender split the data. UDP sends each piece as it is, with no connection, and takes no responsibility for whether it arrives.

Partly checked against real execution · Six of the eight combinations were run on 127.0.0.1 with the net and dgram modules of Node.js 24 and checked. The two combinations of TCP with a loss or a reordering are based on RFC 9293

Concepts in this lab

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.
Byte stream and datagram
These are the two shapes in which data is carried. A byte stream is a flow in which bytes continue in order without a break, and TCP works this way. How many writes the sender used is not passed on, so data sent in three writes may be read in one read, and data sent in one write may be read in several reads. A datagram is a way in which a piece sent at one time is delivered as it is, as a single unit, and UDP works this way; pieces are not merged or split when they are read. So a program that exchanges messages over TCP has to mark the end of a message itself, by writing the length first or by putting in a delimiter.
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.
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.
Three-way handshake
The three-step process used to establish a TCP connection. The client sends a connection request (SYN), the server sends its acceptance together with its own connection request (SYN+ACK), and the client acknowledges it (ACK). After both sides have confirmed that they can send to and receive from each other, data transfer starts.

Try these

Running with the default settings

  1. net.connect(9000, '127.0.0.1'): TCP establishes a connection before it sends any data (the three-way handshake). A program is waiting on port 9000, so this succeeds. From now on, the operating systems on both sides number the bytes that travel over this connection and keep track of them.
  2. socket.write('AB'): the 2 bytes arrive at the receiver's operating system and are added to the receive buffer. The receiving program has not read yet, so the operating system holds it. The TCP buffer is a single line in which bytes pile up one after another.
  3. socket.write('CD'): the 2 bytes arrive at the receiver's operating system and are added to the receive buffer. They follow right after the earlier bytes. Where one write ended and the next began is not recorded.
  4. socket.write('EF'): the 2 bytes arrive at the receiver's operating system and are added to the receive buffer. They also follow the earlier bytes, so the buffer holds 6 bytes in a single line.
  5. The receiving program reads: a single 'data' event delivers all 6 bytes, "ABCDEF". There is no trace of the data having been sent in three writes. What TCP delivers is a stream of bytes in the correct order, not the boundaries between pieces.

Result of this run

Code

// Node.js (net module): TCP
const socket = net.connect(9000, '127.0.0.1');   // establish the connection first
socket.on('connect', async () => {               // data can be sent only after it is connected
  socket.write('AB');  await sleep(50);           // three times, at 0.05-second intervals
  socket.write('CD');  await sleep(50);
  socket.write('EF');
});
socket.on('error', e => console.log(e.code));    // a connection failure arrives here

// Receiving program: starts reading after all three have arrived
net.createServer({ pauseOnConnect: true }, conn => {
  conn.on('data', d => console.log(d.toString()));
  setTimeout(() => conn.resume(), 500);
}).listen(9000, '127.0.0.1');

Assumptions of this model

This is a case in which "AB", "CD", and "EF" are sent at 0.05-second intervals and the receiving program reads after all three have arrived. Six of the eight combinations were actually run with the net and dgram modules on 127.0.0.1 of the PC used to write this lab (Windows, Node.js 24) and checked against the model (each combination was run five times, with the same result every time). The loss and the reordering of UDP were created by placing a relay program between the sender and the receiver that drops or delays datagrams, and it was confirmed that the UDP sockets at both ends do not correct this. The two combinations in which TCP has a loss or a reordering could not be created on this PC and were not run; following the TCP specification (RFC 9293, sequence numbers in section 3.4, and acknowledgments and retransmission in section 3.8), the lab states that "what the program reads is the same as when nothing went wrong." That all 6 bytes came out in a single read with TCP is the result seen on this PC, and what the specification guarantees is only the order and the content of the bytes. How many reads the data is divided into varies with the circumstances. That UDP delivers in units of datagrams and does not guarantee arrival is stated in RFC 768 and in RFC 1122 section 4.1. The UDP header has no number that shows order (RFC 768), and the IP below it does not keep order either (RFC 791 section 1.2). The operating system sometimes reports with an ICMP message that no receiving program exists, but in this run nothing came back as a result of send or as an error event. The case in which data is discarded because the buffer of the operating system is full is not covered.

Previous lab: TCP connections and retransmission · Next lab: Flow control and congestion control

Concepts in this lab

What this lab shows

Settings

Code


      
    

Diagram

Run comparison

Try these