Common Level Options
What are Common TCP-Level Options?
TCP-level options are optional fields in the TCP header that enhance performance, reliability, and control. They allow fine-tuning of the TCP connection behavior.
Why are TCP-Level Options useful?
These options allow features such as window scaling, selective acknowledgments, and timestamps, which improve performance, especially in high-latency or high-bandwidth networks.
How do TCP-Level Options work?
TCP options are inserted into the optional section of the TCP header during the connection setup (like in the SYN packet) and negotiated between sender and receiver to enable specific enhancements.
Where are TCP-Level Options used?
They are used in almost all modern TCP implementations — in servers, clients, routers, and middleboxes — to improve throughput, error recovery, and congestion handling.
Which OSI layer do TCP-Level Options belong to?
TCP-level options operate at the Transport Layer (Layer 4) of the OSI model.
Are TCP-Level Options Windows specific?
No, TCP options are implemented across all major operating systems including Windows, Linux, and macOS.
Are TCP-Level Options Linux specific?
No, Linux does support advanced TCP options, but these are standard across modern OS implementations.
Which Transport Protocol uses TCP-Level Options?
TCP (Transmission Control Protocol) is the transport protocol that uses TCP-level options to enhance connection capabilities.
Are TCP-Level Options used in the client-server model?
Yes, TCP-level options are widely used in client-server communications to improve reliability, speed, and adaptability of network connections.
In this section, you are going to learn
Terminology
Version Info
TCP_NODELAY C Code (Client-Server Model over TCP without TCP_NODELAY)
This C program demonstrates the default TCP_NODELAY behavior where Nagle’s algorithm is enabled.
The TCP server listens on a TCP port, accepts client connections, and sends/receives data normally.
The TCP client connects to the server and sends small messages without setting TCP_NODELAY.
With Nagle’s algorithm ON, TCP may combine multiple small writes into a single larger packet before transmission.
This setup is useful for testing the standard TCP packetization behavior and comparing it with TCP_NODELAY enabled (Nagle OFF).
Replace the server IP address (127.0.0.1) in the client code with your actual server address before running.
Step-1: Download C source code for TCP_NODELAY server and client.
Step-2: Convert C code to executable files.
test:~$gcc tcp_nodelay_server_t1.c -o tcp_nodelay_server test:~$gcc tcp_nodelay_client_t1.c -o tcp_nodelay_client
Step-3: Run TCP server and client.
# # Start TCP server test:~$./tcp_nodelay_server TCP server listening on port 5050... # Run TCP client test:~$ ./tcp_nodelay_client Sent messages with TCP_NODELAY enabled
Step-4: Wireshark Capture
To check the exact output in above pcap in wireshark use filter: tcp.port==5050
Expected Wireshark Observations:
Small writes from the client may be merged into a single TCP segment before being sent.
Fewer packets are transmitted compared to TCP_NODELAY (Nagle OFF).
Slightly higher latency may be observed since TCP waits to accumulate data before sending.
More efficient bandwidth usage is achieved because multiple small messages are combined into fewer packets.
TCP_NODELAY C Code (Client-Server Model over TCP with TCP_NODELAY)
This C program demonstrates how to disable Nagle’s algorithm using the TCP_NODELAY socket option.
The TCP server listens on a TCP port, accepts client connections, and exchanges messages.
The TCP client connects to the server and sets TCP_NODELAY with setsockopt().
With Nagle’s algorithm OFF, each send() immediately transmits a TCP segment, even if it is small.
This setup is useful for applications needing low latency (e.g., real-time systems, chat apps, financial trading) where timely delivery is more important than bandwidth efficiency.
Replace the server IP address (127.0.0.1) in the client code with your actual server address before running.
Step-1: Download C source code for TCP_NODELAY server and client.
Download TCP_NODELAY Server Code
Download TCP_NODELAY Client Code
Step-2: Compile the programs.
test:~$gcc tcp_nodelay_server_t2.c -o tcp_nodelay_server test:~$gcc tcp_nodelay_client_t2.c -o tcp_nodelay_client
Step-3: Run TCP server and client.
# Start TCP server test:~$ ./tcp_nodelay_server TCP server listening on port 5050... # Run TCP client test:~$ ./tcp_nodelay_client Sent messages with TCP_NODELAY enabled (Nagle’s algorithm OFF)
Step-4: Wireshark Capture & Explanation
To check the exact output in above pcap in wireshark use filter: tcp.port==5050
Expected Wireshark Observations:
Each send() call from the client generates an immediate TCP packet.
Multiple small packets appear on the network (no coalescing/merging).
Lower latency is observed since data is sent right away.
TCP_CORK C Code (Client-Server Model over TCP with TCP_CORK Enable)
- This C program demonstrates how to enable TCP_CORK using the setsockopt() system call.
The TCP server listens on a TCP port, accepts client connections, and sends responses.
The TCP client connects to the server and enables TCP_CORK.
With TCP_CORK enabled, small writes are buffered until either the buffer is full or the option is cleared, then transmitted together in a larger segment.
This setup is useful for reducing fragmentation and improving throughput when sending multiple small chunks of data.
Replace the server IP address (127.0.0.1) in the client code with your actual server address before running.
Step-1: Download C source code for TCP_CORK server and client.
Step-2: Compile the programs.
test:~$gcc tcp_cork_server_t1.c -o tcp_cork_server test:~$gcc tcp_cork_client_t1.c -o tcp_cork_client
Step-3: Run TCP server and client.
# Start TCP server test:~$ ./tcp_cork_server TCP server listening on port 8080... # Run TCP client test:~$ ./tcp_cork_client Sent messages with TCP_CORK enabled
Step-4: Wireshark Capture & Explanation
To check the exact output in above pcap in wireshark use filter: tcp.port==8080
Expected Wireshark Observations:
Multiple small writes are not sent immediately but buffered together.
A larger TCP segment is transmitted when the cork is removed or buffer flushes.
Fewer packets appear compared to TCP_NODELAY.
Throughput efficiency improves, but latency increases slightly.
TCP_CORK C Code (Client-Server Model over TCP without TCP_CORK Disable)
- This C program demonstrates the default TCP behavior where TCP_CORK is not enabled.
The TCP server listens on a TCP port, accepts client connections, and sends responses.
The TCP client connects to the server and sends multiple small writes without using TCP_CORK.
Each write may be sent as an independent TCP segment (unless Nagle’s algorithm combines them).
This setup is useful for comparing the default TCP send behavior with the optimized buffering provided by TCP_CORK.
Replace the server IP address (127.0.0.1) in the client code with your actual server address before running.
Step-1: Download C source code for TCP server and client (without TCP_CORK).
Step-2: Compile the programs.
test:~$gcc tcp_cork_server_t2.c -o tcp_cork_server test:~$gcc tcp_cork_client_t2.c -o tcp_cork_client
Step-3: Run TCP server and client.
# Start TCP server test:~$ ./tcp_server TCP server listening on port 8080... # Run TCP client test:~$ ./tcp_client Sent messages with default TCP behavior (TCP_CORK disabled)
Step-4: Wireshark Capture & Explanation
To check the exact output in above pcap in wireshark use filter: tcp.port==8080
Expected Wireshark Observations:
Each send() may result in a separate TCP packet.
More packets are visible compared to TCP_CORK enabled.
Lower latency per message, but higher overhead due to small packet sizes.
Useful for interactive or low-latency communication, less efficient for bulk transfers.
TCP_KEEPALIVE C Code (Client-Server Model with Keepalive Options)
- This C program demonstrates TCP keepalive configuration using socket options:
SO_KEEPALIVE – Enables keepalive mechanism on a socket.
TCP_KEEPIDLE – Time (in seconds) the connection must be idle before keepalive probes start.
TCP_KEEPINTVL – Interval (in seconds) between successive keepalive probes.
TCP_KEEPCNT – Maximum number of keepalive probes to send before declaring the connection dead.
The TCP server listens on a TCP port, accepts client connections, and prints received data.
The TCP client connects to the server, sends a message, and stays idle to allow keepalive probes.
This setup is useful to observe keepalive packets in Wireshark and understand failure detection.
Step-1: Download C source code for TCP server and client (with keepalive settings).
Step-2: Compile the programs.
test:~$ gcc tcp_keepalive_server.c -o tcp_keepalive_server test:~$ gcc tcp_keepalive_client.c -o tcp_keepalive_client
Step-3: Run TCP server and client.
# Start TCP server test:~$ ./tcp_keepalive_server TCP server listening on port 9090... # Run TCP client test:~$ ./tcp_keepalive_client Sent message and waiting (keepalive enabled)...
Step-4: Wireshark Capture & Explanation
Download Wireshark capture
Download Wireshark capture
To check the exact output in above pcap in wireshark use filter: tcp.port==9090.
Expected Wireshark Observations:
After KEEPIDLE seconds of client inactivity, server starts sending TCP keepalive probes.
Keepalive probes are retransmitted at intervals defined by KEEPINTVL.
If no response is received after KEEPCNT probes, the connection is declared dead and closed.
In Wireshark, keepalive probes appear as duplicate ACKs with 1-byte sequence difference.
This mechanism helps detect broken connections when the client is silent or unreachable.
TCP_MAXSEG C Code (Client-Server Model with TCP_MAXSEG Option)
- This C program demonstrates the use of TCP_MAXSEG socket option:
TCP_MAXSEG sets the maximum segment size (MSS) for TCP packets on a connection.
It controls the maximum data payload that TCP will place in a single segment.
Useful for testing fragmentation, MTU-related behavior, and optimizing throughput.
The TCP server listens on a TCP port and prints received data.
The TCP client connects to the server, configures TCP_MAXSEG, and sends a large message.
This setup is useful to observe how packet segmentation changes in Wireshark.
Step-1: Download C source code for TCP server and client (with TCP_MAXSEG option).
Step-2: Compile the programs.
test:~$ gcc tcp_maxseg_server.c -o tcp_maxseg_server test:~$ gcc tcp_maxseg_client.c -o tcp_maxseg_client
Step-3: Run TCP server and client.
# Start TCP server test:~$ ./tcp_maxseg_server TCP server listening on port 9090... # Run TCP client test:~$ ./tcp_maxseg_client Sent message with custom TCP_MAXSEG value
Step-4: Wireshark Capture & Explanation
To check the exact output in above pcap in wireshark use filter: tcp.port==9090.
Expected Wireshark Observations:
TCP segments are limited to the size set by TCP_MAXSEG (excluding headers).
For example, if TCP_MAXSEG = 512, large messages will be broken into 512-byte segments.
Smaller MSS leads to more packets with higher overhead but may avoid fragmentation.
Larger MSS improves throughput efficiency but may risk fragmentation if MTU is smaller.
In Wireshark, you can verify MSS under TCP options during the 3-way handshake and check segment sizes in the data packets.
TCP_INFO C Code (Client-Server Model with TCP_INFO Option)
- This C program demonstrates the use of TCP_INFO socket option:
TCP_INFO provides detailed information about a TCP connection (e.g., RTT, congestion window, retransmissions).
It is a read-only option used with getsockopt().
Useful for debugging, performance monitoring, and real-time TCP state inspection.
The TCP server listens on a TCP port, accepts client connections, and retrieves TCP_INFO details.
The TCP client connects to the server and sends data, allowing the server to inspect live TCP state.
This setup is useful to understand internal TCP metrics visible via socket options.
Step-1: Download C source code for TCP server and client (with TCP_INFO).
Step-2: Compile the programs.
test:~$ gcc tcp_info_server.c -o tcp_info_server test:~$ gcc tcp_info_client.c -o tcp_info_client
Step-3: Run TCP server and client.
# Start TCP server test:~$ ./tcp_info_server TCP server listening on port 9090... # Run TCP client test:~$ ./tcp_info_client Sent test message to server
Step-4: Wireshark Capture & Explanation
To check the exact output in above pcap in wireshark use filter: tcp.port==9090.
Expected Wireshark Observations:
Normal TCP handshake and data transfer packets are visible.
Unlike TCP_MAXSEG or TCP_CORK, TCP_INFO does not alter packet flow — it only queries socket statistics.
No additional packets are generated by TCP_INFO; it is local to the host kernel.
TCP state (e.g., RTT, cwnd, retransmits) can be observed programmatically but not directly in Wireshark.
Wireshark captures help correlate observed traffic with TCP_INFO values retrieved in the server logs.
TCP_CONGESTION C Code (Client-Server Model with TCP_CONGESTION Option)
- This C program demonstrates the use of TCP_CONGESTION socket option:
TCP_CONGESTION allows setting or getting the congestion control algorithm for a TCP socket.
- Common congestion control methods available on Linux:
cubic (default on most modern Linux systems, good for high-speed long-distance links)
reno (classic congestion avoidance algorithm, simple but less efficient on high BDP networks)
bbr (Bottleneck Bandwidth and RTT, modern algorithm focusing on throughput and latency)
Using setsockopt() with TCP_CONGESTION, applications can switch algorithms per connection.
The TCP server listens on a TCP port and receives messages.
The TCP client connects to the server, sets the desired congestion control algorithm, and sends data.
This setup is useful for comparing congestion control behaviors in Wireshark.
Step-1: Download C source code for TCP server and client (with TCP_CONGESTION option).
Step-2: Compile the programs.
test:~$ gcc tcp_congestion_server.c -o tcp_congestion_server test:~$ gcc tcp_congestion_client.c -o tcp_congestion_client
Step-3: Run TCP server and client.
# Start TCP server test:~$ ./tcp_congestion_server TCP server listening on port 9090... # Run TCP client test:~$ ./tcp_congestion_client Sent message from the server
Step-4: Wireshark Capture & Explanation
Download Wireshark capture (CUBIC)
In above pcap for observing cubic, reno, BBR go for statistics option and then open TCP STREAM GRAPHS we can observe in graph these common congestion control methods.
Expected Wireshark Observations:
CUBIC: Aggressive window growth, faster throughput recovery after loss, visible as a steep cwnd ramp-up.
RENO: Linear congestion avoidance, slower recovery, more conservative than cubic.
BBR: Sends at bottleneck bandwidth × RTT, maintains lower latency with smoother packet pacing.
Different algorithms show distinct patterns in packet burst, retransmissions, and ACK pacing.
Useful for experimenting with TCP performance tuning and understanding trade-offs of each algorithm.
TCP_DEFER_ACCEPT C Code (Client-Server Model with TCP_DEFER_ACCEPT Option)
- This C program demonstrates the use of TCP_DEFER_ACCEPT socket option:
TCP_DEFER_ACCEPT delays the accept() return on the server until data arrives on the socket.
It reduces wakeups for idle connections and ensures that the server only handles connections with data ready.
Useful for reducing overhead from empty TCP handshakes (e.g., in HTTP servers).
The TCP server listens on a TCP port with TCP_DEFER_ACCEPT enabled.
The TCP client connects to the server and sends data after a delay.
This setup is useful to observe how accept() behavior changes and confirm using Wireshark.
Step-1: Download C source code for TCP server and client (with TCP_DEFER_ACCEPT).
Step-2: Compile the programs.
test:~$ gcc tcp_defer_accept_server.c -o tcp_defer_accept_server test:~$ gcc tcp_defer_accept_client.c -o tcp_defer_accept_client
Step-3: Run TCP server and client.
# Start TCP server test:~$ ./tcp_defer_accept_server TCP server listening on port 9090 (TCP_DEFER_ACCEPT enabled)... # Run TCP client test:~$ ./tcp_defer_accept_client Connected to server, sending data after delay...
Step-4: Wireshark Capture & Explanation
To check the exact output in above pcap in wireshark use filter: tcp.port==9090.
Expected Wireshark Observations:
Normal 3-way handshake occurs when the client connects.
Unlike default behavior, the server’s accept() call does not return immediately after handshake.
Server only wakes up once the client sends application data.
In Wireshark, you will see the handshake followed by a pause until the client sends its first payload.
This reduces empty connections and can improve efficiency for short-lived request/response protocols.
TCP_QUICKACK C Code (Client-Server Model with TCP_QUICKACK Option)
- This C program demonstrates the use of TCP_QUICKACK socket option:
TCP_QUICKACK controls whether TCP delays acknowledgments (ACKs) or sends them immediately.
By default, Linux may delay ACKs to reduce overhead (delayed ACK algorithm).
Enabling TCP_QUICKACK forces immediate ACKs after data reception.
Disabling it allows the kernel to use delayed ACKs again.
The TCP server listens on a TCP port and receives data from the client.
The TCP client connects to the server, sends messages, and the server controls ACK behavior using TCP_QUICKACK.
This setup is useful for comparing ACK timing in Wireshark.
Step-1: Download C source code for TCP server and client (with TCP_QUICKACK).
Step-2: Compile the programs.
test:~$ gcc tcp_quickack_server.c -o tcp_quickack_server test:~$ gcc tcp_quickack_client.c -o tcp_quickack_client
Step-3: Run TCP server and client.
# Start TCP server test:~$ ./tcp_quickack_server TCP server listening on port 9090 (TCP_QUICKACK enabled)... # Run TCP client test:~$ ./tcp_quickack_client Sent test messages to server
Step-4: Wireshark Capture & Explanation
To check the exact output in above pcap in wireshark use filter: tcp.port==9090.
Expected Wireshark Observations:
With TCP_QUICKACK enabled, each received segment is acknowledged immediately.
With TCP_QUICKACK disabled, ACKs may be delayed and piggybacked with outgoing data.
Immediate ACKs improve latency but increase packet overhead.
Delayed ACKs reduce packet count but may slightly increase round-trip latency.
In Wireshark, you can compare back-to-back ACKs (quickack) vs. grouped ACKs (delayed).
Reference links