TCP & UDP

TCP (Transmission Control Protocol) and UDP (User Datagram Protocol) are two of the most important protocols used by applications to communicate across IP networks.

Both operate at the Transport Layer (Layer 4) of the OSI model and sit above the network Layer. Their job is to take data generated by applications and provide a mechanism for delivering that data between applications running on different devices.

Although TCP and UDP perform broadly the same job, they do it in very different ways: TCP is designed to provide reliable, ordered and connection-oriented communication, whereas UDP is designed to provide fast, lightweight and connectionless communication, without TCP’s mechanisms for guaranteeing delivery and ordering.

The choice between TCP and UDP therefore depends on what an application needs.

A file transfer, for example, cannot afford to silently lose part of a file. A small amount of additional overhead and retransmission is acceptable, so TCP is appropriate, but a live voice or video conversation has different requirements. If a packet containing a piece of audio is lost, retransmitting it several seconds later is usually pointless because the conversation has already moved on. In this situation, UDP may be a better choice.

What is TCP?

The Transmission Control Protocol provides a reliable, connection-oriented transport service between two applications.

When an application uses TCP, the two endpoints establish a connection via a mechanism known as the TCP 3-way handshake before application data is exchanged. TCP then keeps track of the data being transmitted and uses sequence numbers, acknowledgements, retransmissions and flow-control mechanisms to make sure that data can be delivered reliably.

TCP provides several important characteristics:

  • Connection-oriented communication
  • Reliable delivery
  • Ordered delivery
  • Error detection
  • Retransmission of lost data
  • Flow control
  • Congestion control
  • Duplicate detection

TCP does not simply send a stream of packets and hope that everything arrives. Instead, it maintains a considerable amount of state about the connection.

This allows TCP to answer questions such as:

Which data has been sent?

Which data has been received?

Which data has been acknowledged?

How much data can the receiver accept?

Has something been lost?

Is the network becoming congested?

This additional functionality is what makes TCP reliable, but it also introduces additional overhead.

What is UDP?

User Datagram Protocol takes a much simpler approach. There is no connection establishment, no 3-way handshake, no sequence numbering and no mechanism within UDP itself for retransmitting lost datagrams.

An application simply provides UDP with some data and a destination port, and UDP places that data into a datagram and passes it to IP for transmission.

UDP provides:

  • Source and destination ports
  • Datagram delivery
  • A length field
  • Error detection through a checksum

It does not provide:

  • Guaranteed delivery
  • Guaranteed ordering
  • Retransmission
  • Connection establishment
  • Flow control
  • Congestion control

This makes UDP considerably simpler than TCP.

The UDP header contains only four fields: source port, destination port, length and checksum.

TCP and UDP operate above IP

It is important to understand where TCP and UDP fit into the networking stack.

A typical communication might look something like this:

Application
    │
    │ HTTP / DNS / SSH / etc.
    ▼
Transport Layer
    │
    ├── TCP
    │
    └── UDP
    │
    ▼
Internet Layer
    │
    └── IP
    │
    ▼
Network Access
    │
    └── Ethernet / Wi-Fi

IP is responsible for getting packets from one IP address to another. TCP and UDP provide the transport mechanism that allows multiple applications to communicate using the same network connection.

This is where port numbers become important.

For example:

192.168.1.10:49152
        │
        │ TCP
        │
        ▼
192.168.1.20:443

The IP addresses identify the networks and hosts

The port numbers identify the applications or services on the hosts

This allows a single computer to simultaneously communicate with a web server, DNS server, SSH server and dozens of other services.

TCP Ports

TCP uses a 16-bit source port and a 16-bit destination port.

This gives a possible range of:

0 – 65535

Ports from 0–1023 are known as well-known ports and are traditionally associated with common services.

Some examples include:

PortProtocolTypical use
20/21TCPFTP
22TCPSSH
23TCPTelnet
25TCPSMTP
80TCPHTTP
443TCPHTTPS
3389TCPRDP

A client will normally use a temporary ephemeral port as its source port.

For example:

Client

192.168.1.50:51542
        │
        │ TCP
        ▼
Web Server

192.168.1.100:443

The server listens on port 443 while the client uses a temporary port such as 51542.

The combination of IP addresses and ports allows the operating system to identify the particular communication session.

The TCP Header

TCP adds a header to application data before passing the resulting segment to IP.

A TCP header contains a number of important fields.

  0                   15 16                  31
  ┌─────────────────────┬──────────────────────────┐
  │     Source Port   │  Destination Port      │
  ├─────────────────────┴──────────────────────────┤
  │              Sequence Number               │
  ├────────────────────────────────────────────────┤
  │           Acknowledgment Number            │
  ├───────┬───────┬────────────────────────────────┤
  │Offset│ Flags │          Window             │
  ├───────┴───────┼────────────────────────────────┤
  │    Checksum  │       Urgent Pointer        │
  ├───────────────┴────────────────────────────────┤
  │                 Options                    │
  ├────────────────────────────────────────────────┤
  │                   Data                     │
  └────────────────────────────────────────────────┘

The current TCP specification defines the source and destination ports, sequence number, acknowledgement number, data offset, control flags, window, checksum, urgent pointer and optional TCP options.

Let’s examine the important fields.

Source Port

The source port identifies the application sending the data.

For example:

Source Port: 51542

This would normally be an ephemeral client port.

Destination Port

The destination port identifies the service receiving the data.

For example:

Destination Port: 443

Port 443 is commonly used for HTTPS.

Sequence Number

The sequence number is one of the most important fields in TCP.

TCP treats application data as a continuous stream of bytes. Each byte is assigned a position within that stream.

For example, imagine an application wants to send:

HELLO WORLD

TCP assigns sequence numbers to the bytes. The receiver can therefore determine where each piece of data belongs.

The sequence number in a TCP segment identifies the sequence number of the first data byte carried by that segment. During connection establishment, SYN uses the sequence number to establish an Initial Sequence Number (ISN).

This is what allows TCP to handle:

  • Segments arriving out of order
  • Lost segments
  • Duplicate segments
  • Retransmissions
  • Large streams of data

TCP Acknowledgement Numbers

TCP uses acknowledgement numbers to tell the sender what data has successfully been received.

The acknowledgement number normally represents:

The next sequence number the receiver expects to receive.

For example:

Sender → Receiver

SEQ = 1000
Data = 500 bytes

The receiver has successfully received bytes 1000 through 1499.

It can therefore respond:

ACK = 1500

This means:

“I have received everything up to byte 1499. I am now expecting byte 1500.”

This is called a cumulative acknowledgement.

It is a fundamental part of TCP’s reliability mechanism.

TCP Three-Way Handshake

Before TCP can exchange application data, the two endpoints establish a connection. This is known as the TCP 3-way handshake.

It consists of:

Client                         Server
  │                              │
  │ ─────── SYN ───────────────►   │
  │                              │
  │ ◄──── SYN + ACK ────────────  │
  │                              │
  │ ─────── ACK ───────────────►   │
  │                              │
  │       CONNECTION OPEN        │

The three packets are:

  1. SYN
  2. SYN + ACK
  3. ACK

Step 1 – SYN

The client wants to establish a TCP connection.

It sends a TCP segment with the SYN flag set.

For example:

Client → Server

SYN
SEQ = 1000

The client is effectively saying:

“I want to establish a TCP connection, and my initial sequence number is 1000.”

Step 2 – SYN + ACK

The server receives the SYN and responds.

Server → Client

SYN + ACK
SEQ = 5000
ACK = 1001

The server is saying:

“I acknowledge your SYN and my initial sequence number is 5000.”

Notice that the acknowledgement number is:

1000 + 1 = 1001

The SYN consumes one sequence number even though it does not contain application data.

Step 3 – ACK

The client responds:

Client → Server

ACK
SEQ = 1001
ACK = 5001

The connection is now established.

Both sides know the initial sequence numbers of the other endpoint and can begin exchanging application data.

Why Does TCP Need a Three-Way Handshake?

The handshake does more than simply say “hello”. It allows both endpoints to establish synchronised sequence-number state.

The client establishes its initial sequence number.

The server establishes its initial sequence number.

Both sides acknowledge that they have received the other’s value.

This gives TCP the information it needs to maintain the connection and track data reliably. It also explains why a TCP connection is described as stateful.

TCP maintains information about the connection throughout its lifetime.

TCP Sequence Numbers in Action

Imagine a client is sending a 5,000-byte file.

TCP might divide the data into several segments:

Segment 1
SEQ = 1001
Length = 1000

Segment 2
SEQ = 2001
Length = 1000

Segment 3
SEQ = 3001
Length = 1000

Segment 4
SEQ = 4001
Length = 1000

Segment 5
SEQ = 5001
Length = 1000

The receiver can acknowledge the data as it arrives.

For example:

ACK = 2001

means:

“I have received everything up to sequence number 2000.”

If everything subsequently arrives:

ACK = 3001
ACK = 4001
ACK = 5001
ACK = 6001

TCP can therefore keep track of exactly which parts of the stream have arrived.

What Happens If a Segment Is Lost?

Suppose the sender transmits:

SEQ 1001
SEQ 2001
SEQ 3001
SEQ 4001

but the segment containing sequence number 2001 is lost.

The receiver receives:

1001
3001
4001

It knows that it is still waiting for:

2001

It can therefore continue acknowledging the last contiguous data it has received.

The sender can detect that something has gone wrong and retransmit the missing data.

This is one of the fundamental mechanisms that gives TCP reliable delivery.

TCP Sliding Windows

Sending one segment and then waiting for an acknowledgement before sending the next would be extremely inefficient.

Imagine a connection between two computers separated by thousands of kilometres.

If the sender had to wait for an acknowledgement after every packet, much of the available network capacity would sit unused while packets travelled back and forth.

TCP solves this problem using windows.

The TCP receive window tells the sender how much data the receiver is currently willing to accept. RFC 9293 defines the window as the number of data octets, beginning at the acknowledged sequence number, that the receiver is willing to accept.

For example:

Window = 4000 bytes

The sender can transmit up to 4,000 bytes without waiting for every individual segment to be acknowledged.

Conceptually:

┌─────────────── TCP Receive Window ───────────────┐
│                                                │
│  SENT & ACKED │   SENT │       AVAILABLE       │
│               │        │                       │
└────────────────────────────────────────────────────┘

As acknowledgements arrive, the window moves forward.

This is why it is called a sliding window.

Why Sliding Windows Matter

The sliding window provides flow control.

Imagine a very fast server sending data to a slow computer. Without flow control, the server could send data much faster than the receiver could process it. The receiver could become overwhelmed.

The TCP window allows the receiver to tell the sender:

“This is how much additional data I can currently accept.”

If the receiver has very little buffer space available, it can advertise a smaller window. If it has plenty of available buffer space, it can advertise a larger window.

TCP therefore allows the receiver to control how much unacknowledged data can be outstanding.

Window Scaling

The original TCP window field is 16 bits.

That gives a maximum advertised value of:

65,535 bytes

Modern high-speed networks can require considerably larger windows. TCP therefore supports window scaling, which allows the effective window size to be much larger.

The window-scaling option is negotiated during connection establishment.

This becomes particularly important on high-bandwidth networks with significant latency, where a small window could prevent the connection from making full use of the available bandwidth.

Flow Control vs Congestion Control

These two concepts are often confused.

Flow control protects the receiver.

It answers:

“Can the receiving computer handle more data?”

Congestion control protects the network.

It answers:

“Can the network handle more data?”

TCP uses mechanisms such as the congestion window to regulate how aggressively data is transmitted.

A TCP sender therefore has to consider both:

Receiver capacity
        +
Network capacity
        =
How much data can be sent

This is one of the reasons TCP is considerably more sophisticated than UDP.

TCP Flags

TCP contains a number of control flags.

These flags tell the receiving TCP implementation how to interpret the segment and what action may be required.

The current TCP specification defines eight active control flags:

  • CWR
  • ECE
  • URG
  • ACK
  • PSH
  • RST
  • SYN
  • FIN

These are particularly important when analysing network traffic with tools such as Wireshark.

SYN – Synchronise

SYN is used when establishing a TCP connection.

It indicates that the sender is synchronising sequence numbers.

Example:

Client → Server

SYN
SEQ = 1000

SYN is normally seen during the TCP three-way handshake.

A SYN packet with no ACK is normally the initial connection request.

ACK – Acknowledgement

The ACK flag indicates that the acknowledgement number field is valid.

Once a TCP connection has been established, ACK is present on normal TCP segments carrying acknowledgements.

For example:

ACK = 5001

means the receiver is expecting sequence number 5001 next.

The ACK flag is therefore central to TCP’s acknowledgement mechanism.

FIN – Finish

The FIN flag indicates that the sender has no more data to send.

It is used when closing a TCP connection.

For example:

Client → Server

FIN + ACK

The receiving endpoint can acknowledge the FIN and eventually close its own side of the connection.

Because TCP connections are bidirectional, each direction can be closed independently.

RST – Reset

The RST flag indicates that the connection should be reset.

A TCP reset can occur for several reasons.

For example, a host might receive a TCP connection attempt for a port where no application is listening.

The host can respond:

RST

effectively saying:

“There is no connection here.”

RST can also appear when an existing connection becomes invalid or an endpoint needs to terminate it immediately.

RST is particularly interesting when analysing network traffic because unexpected resets can indicate connectivity problems, application failures, firewall behaviour or other network conditions.

PSH – Push

The PSH flag indicates the TCP push function.

Historically, this was associated with asking the receiving TCP implementation to make received data available to the application promptly rather than waiting for additional data to fill a buffer.

It is important not to interpret PSH as meaning:

“This packet is important.”

It is a TCP mechanism associated with delivery of received data to the application.

Modern applications generally do not need to manipulate PSH directly.

URG – Urgent

The URG flag indicates that the urgent pointer field is significant.

The urgent mechanism allows a sender to identify urgent data within the TCP stream.

The mechanism is now rarely used by modern applications, and RFC 9293 notes that new applications should not employ it because of implementation differences and middlebox issues.

Nevertheless, the field and flag remain part of TCP and can appear in packet captures.

ECE – ECN Echo

ECE stands for ECN-Echo.

It is associated with Explicit Congestion Notification (ECN).

ECN allows network devices to signal congestion without necessarily having to drop packets.

ECE is used by TCP to communicate ECN-related information between endpoints.

It is therefore more commonly encountered when examining modern TCP traffic than many people initially realise.

CWR – Congestion Window Reduced

CWR stands for Congestion Window Reduced.

It is also associated with Explicit Congestion Notification.

When a sender receives an indication of congestion through ECN, it can reduce its congestion window.

The CWR flag is then used to communicate that the sender has responded to the congestion indication.

TCP Flags at a Glance

FlagNamePurpose
SYNSynchroniseEstablishes/synchronises sequence numbers
ACKAcknowledgementIndicates acknowledgement number is valid
FINFinishSender has no more data
RSTResetImmediately resets a connection
PSHPushRequests prompt delivery of data to the application
URGUrgentIndicates urgent pointer is significant
ECEECN EchoCommunicates ECN congestion information
CWRCongestion Window ReducedIndicates congestion response

A useful way to remember the most important flags is:

SYN  → Start
ACK  → Acknowledge
FIN  → Finish
RST  → Reset

These four appear particularly frequently when analysing TCP connections.

Closing a TCP Connection

Establishing a TCP connection requires three stages.

Closing one normally involves a four-segment exchange because each direction of the connection is closed independently.

A simplified example looks like this:

Client                         Server
  │                              │
  │ ─────── FIN ───────────────►   │
  │                              │
  │ ◄────── ACK ────────────────   │
  │                              │
  │ ◄────── FIN ────────────────   │
  │                              │
  │ ─────── ACK ───────────────►   │
  │                              │
  │        CONNECTION CLOSED     │

The important point is that TCP is full duplex.

The client can finish sending data while the server may still have data to send.

This is why closing a TCP connection is not simply a single “goodbye” packet.

TCP TIME_WAIT

After a TCP connection has been closed, the endpoint that performs the active close may enter the TIME_WAIT state.

This state exists for an important reason.

Old TCP segments could still exist somewhere in the network.

If the same IP addresses and ports were immediately reused for a new connection, delayed packets from the previous connection could potentially be mistaken for packets belonging to the new connection.

TIME_WAIT therefore provides a period during which old segments can expire from the network.

This is one reason that systems handling large numbers of short-lived TCP connections can sometimes accumulate significant numbers of sockets in TIME_WAIT.

The UDP Header

UDP is dramatically simpler than TCP.

Its header contains only four fields:

  0                   15 16                  31
  ┌─────────────────────┬─────────────────────────┐
  │     Source Port     │  Destination Port   │
  ├─────────────────────┼─────────────────────────┤
  │       Length        │       Checksum      │
  └─────────────────────┴─────────────────────────┘

Each field is 16 bits.

That means the UDP header is only 8 bytes long.

The fields are:

Source Port

Identifies the sending application.

Destination Port

Identifies the receiving application.

Length

Specifies the length of the UDP datagram, including the UDP header and data.

Checksum

Provides error detection for the UDP header and data.

RFC 768 defines the UDP header and specifies that the length includes both header and data, with 8 bytes being the minimum possible UDP datagram length.

How UDP Works

Suppose a client wants to send a DNS request.

The application creates the DNS request and passes it to UDP.

UDP adds its header:

Source Port       49152
Destination Port  53
Length            ...
Checksum          ...

The resulting UDP datagram is then passed to IP.

IP adds its own header:

Source IP       192.168.1.50
Destination IP  192.168.1.1
Protocol        UDP

The packet is then passed down to Ethernet or Wi-Fi for transmission.

There is no handshake.

There is no:

SYN
SYN/ACK
ACK

The application simply sends the datagram.

What Happens If a UDP Packet Is Lost?

Nothing happens at the UDP layer.

Suppose an application sends:

UDP Datagram 1
UDP Datagram 2
UDP Datagram 3
UDP Datagram 4

and Datagram 3 is lost.

The receiver might receive:

1
2
4

UDP does not automatically detect that Datagram 3 is missing and request it again.

It is up to the application to decide what to do.

An application could:

  • Ignore the missing data
  • Request it again
  • Add its own sequence numbers
  • Implement its own acknowledgements
  • Attempt error correction
  • Continue without it

This is one of the fundamental differences between UDP and TCP.

TCP vs UDP

The simplest comparison is:

FeatureTCPUDP
ConnectionConnection-orientedConnectionless
HandshakeYesNo
ReliabilityYesNo
OrderingYesNo
RetransmissionYesNo
Sequence numbersYesNo
AcknowledgementsYesNo
Sliding windowYesNo
Flow controlYesNo
Congestion controlYesNo
Header sizeMinimum 20 bytes8 bytes
FlagsYesNo
Data modelByte streamDatagram
OverheadHigherLower
Speed/latencyGenerally higher overheadGenerally lower overhead

Neither protocol is inherently “better”.

They are designed for different requirements.

TCP Applications

TCP is particularly useful where reliable delivery is important.

Examples include:

HTTPS – Web applications traditionally use TCP for HTTPS connections. The browser needs reliable delivery because losing part of an HTTP response could corrupt the resulting data.

SSH – SSH requires reliable, ordered communication because commands and responses must arrive correctly.

FTP – File transfers need reliable delivery. A corrupted or incomplete file is generally unacceptable.

Email – Protocols such as SMTP, IMAP and POP3 traditionally use TCP because reliable delivery is important.

UDP Applications

UDP is useful where low overhead, low latency or application-controlled reliability is desirable.

Examples include:

DNS – Traditional DNS queries commonly use UDP because DNS requests and responses are often small and do not require a connection to be established for every exchange. DNS can also use TCP when required.

DHCP – DHCP uses UDP because a client may initially have no usable IP configuration and needs to communicate using broadcast mechanisms.

VoIP – Voice communication is sensitive to delay. A missing voice packet is often less harmful than waiting for it to be retransmitted.

Streaming and Real-Time Applications – Real-time applications may use UDP because they can tolerate some packet loss in exchange for lower latency.

Online Gaming – Games often prioritise timely delivery. If a player’s position update is lost, it may be better to use the next position update rather than retransmit an old one.

Why Doesn’t Everything Use TCP?

At first glance, TCP seems like the obvious choice. Why would anyone deliberately choose a protocol that can lose packets?

Because reliability is not always the most important requirement.

Imagine a video call; Suppose an audio packet containing:

"Hello"

is lost.

TCP would eventually retransmit it.

But imagine that retransmission arrives two seconds later – the conversation has already moved on, so playing the old packet now may actually make the experience worse.

For real-time applications:

Low latency
      ↓
Often more important than
      ↓
Perfect delivery

UDP allows the application developer to make that decision.

TCP Provides a Byte Stream

Another important difference is how TCP and UDP treat data. TCP provides applications with a continuous byte stream.

Suppose an application sends:

HELLO

and then:

WORLD

TCP does not necessarily preserve those as two separate messages.

The receiver might read:

HELLOWORLD

or:

HEL
LOWOR
LD

depending on how the receiving application reads from the TCP socket.

TCP guarantees the ordering of the bytes, but it does not preserve application message boundaries.

UDP Preserves Datagram Boundaries

UDP works differently.

If an application sends:

HELLO

as one UDP datagram and:

WORLD

as another, the receiver receives two separate datagrams. The boundaries are preserved.

This distinction is extremely important when designing network applications.

TCP:

Application
   │
   ├── "HELLO"
   ├── "WORLD"
   │
   ▼
TCP byte stream
   │
   ▼
"HELLOWORLD"

UDP:

Application
   │
   ├── "HELLO" ──► Datagram 1
   │
   └── "WORLD" ──► Datagram 2

TCP and UDP Security

TCP and UDP are not security protocols. Neither provides encryption, and neither provides authentication of the application data.

For example:

TCP
 │
 ▼
TLS
 │
 ▼
Application

TLS can provide encryption and authentication for protocols such as HTTPS.

Similarly, UDP can be used underneath secure protocols.

For example, modern HTTP/3 uses QUIC, which runs over UDP and provides mechanisms that applications need for secure and reliable transport.

This is an important point:

UDP does not mean “insecure”, and TCP does not mean “secure”.

Security is provided by additional protocols and mechanisms above or alongside the transport protocol.

TCP and UDP in Wireshark

TCP and UDP are particularly useful protocols to study using Wireshark.

A TCP connection might look like:

192.168.1.50 → 192.168.1.100
TCP SYN

followed by:

192.168.1.100 → 192.168.1.50
TCP SYN, ACK

and then:

192.168.1.50 → 192.168.1.100
TCP ACK

After that, application data begins to flow.

Useful Wireshark filters include:

tcp

to display TCP traffic.

udp

to display UDP traffic.

You can also examine specific ports:

tcp.port == 443

or:

udp.port == 53

When examining TCP packets, pay particular attention to:

  • Source port
  • Destination port
  • Sequence number
  • Acknowledgement number
  • Window size
  • TCP flags
  • TCP options
  • Retransmissions
  • Duplicate acknowledgements

These fields allow you to reconstruct what is happening within the connection.

TCP and UDP: The Big Picture

TCP and UDP solve the same broad problem:

How can applications communicate across an IP network?

But they approach the problem very differently – TCP builds a stateful connection between two endpoints and then carefully manages the resulting byte stream.

It uses:

Connection establishment
        ↓
Sequence numbers
        ↓
Acknowledgements
        ↓
Sliding windows
        ↓
Retransmissions
        ↓
Flow control
        ↓
Congestion control
        ↓
Connection termination

UDP takes a much simpler approach:

Application data
        ↓
UDP header
        ↓
IP
        ↓
Network

There is no connection to establish. There is no built-in retransmission. There is no sliding window. There is no guarantee that the destination will receive the datagram.

This simplicity is not a weakness. It is one of UDP’s greatest strengths.

The Bottom Line

TCP and UDP are both fundamental Transport Layer protocols, but they are designed around very different philosophies.

TCP prioritises reliability – It establishes a connection, numbers data, acknowledges received information, retransmits lost segments, controls the rate at which data is sent and ensures that the application receives an ordered byte stream.

UDP prioritises simplicity and speed – It adds only a small header and sends independent datagrams without establishing a connection or providing built-in mechanisms for reliability, ordering or flow control.

The choice between them therefore depends upon what the application needs.

If the application needs:

Reliable + Ordered + Guaranteed delivery
                    ↓
                   TCP

If the application needs:

Low overhead + Low latency + Application control
                    ↓
                   UDP

Understanding the difference is fundamental to understanding modern networking.

More importantly for cybersecurity professionals, understanding TCP and UDP at the packet level makes it possible to interpret network traffic, recognise abnormal connections, identify unusual ports, understand firewall logs, analyse packet captures and recognise the network behaviour produced by applications and attacks.

When you understand the TCP handshake, sequence numbers, acknowledgements, windows and flags, a packet capture stops looking like a collection of hexadecimal numbers and starts telling you exactly what two systems are doing to each other across the network.