TCP: ACK, Retransmissions & Timeouts Sockets: Fundamentals of TCP/IP Networks

 

TCP: ACK, Retransmissions & Timeouts
Chapter 58 | Sockets: Fundamentals of TCP/IP Networks β€” Part 2 of 5
πŸ“š TLPI Ch.58
βœ… ACK / RTO
πŸ” Reliability

How Does TCP Guarantee Delivery?

Networks are unreliable. Packets get lost, corrupted, duplicated, or delayed. TCP solves this by using acknowledgements and retransmissions. Every segment sent must be acknowledged by the receiver. If no acknowledgement arrives in time, TCP retransmits the segment automatically.

This is what makes TCP a reliable protocol β€” the application does not have to worry about lost packets. TCP handles it transparently.

Key Terms in This Section

ACK (Acknowledgement) Positive ACK Retransmission RTO (Retransmission Timeout) Delayed ACK Piggybacking Timer

βœ… Positive Acknowledgements

When the receiving TCP gets a segment without errors, it sends a positive acknowledgement (ACK) back to the sender. This ACK tells the sender: “I received everything up to byte N. Send me byte N+1 next.”

If a segment arrives with errors (checksum fails), the receiver simply discards it silently. No negative ACK is sent. The sender detects this through a timeout.

Normal ACK Flow (No Errors)
Sender
➑ Segment (seq=1, data: bytes 1-500)
β¬… ACK (ack=501) “Got 1-500, send 501 next”
➑ Segment (seq=501, data: bytes 501-1000)
β¬… ACK (ack=1001) “Got 501-1000, send 1001 next”
Receiver
ACK number = next byte the receiver expects to get

The ACK number is cumulative: ACK=1001 means “I have received all bytes up to and including byte 1000.” This is also called a cumulative acknowledgement.

⏳ Retransmissions and the RTO Timer

Every time TCP sends a segment, it starts a retransmission timer. If an ACK for that segment does not arrive before the timer expires, TCP assumes the segment was lost and retransmits it.

Retransmission Due to Lost Segment
Sender
➑ Segment (seq=501)   [Timer started ⏱]
❌ Segment LOST in network
⏳ RTO Expires β€” no ACK received
➑ Retransmit Segment (seq=501) [Timer restarted]
β¬… ACK (ack=1001) “Got it!”
Receiver

The key question is: how long should the timer be? Too short β†’ unnecessary retransmissions (wastes bandwidth). Too long β†’ slow recovery from real losses.

TCP solves this with a dynamic RTO (Retransmission Timeout). It continuously measures the Round Trip Time (RTT) β€” the time from sending a segment to receiving its ACK β€” and adjusts the RTO accordingly.

How RTO is Calculated (Simplified)
Measure RTT
Time from send to ACK
β†’
Smooth RTT (SRTT)
Weighted average of RTT samples
β†’
RTO = SRTT + 4Γ—RTTVAR
RTTVAR = RTT variance
RFC 6298 defines the standard algorithm for computing TCP’s RTO

⏳ Delayed ACK & Piggybacking

In a normal request-response protocol (like HTTP), after receiving a request, the server sends a response right away. TCP is smart: instead of sending a separate ACK packet, the server can piggyback the ACK onto the response data it is already sending.

The Delayed ACK technique: instead of sending an ACK immediately on receiving a segment, the receiver waits a short time (typically up to 200ms) to see if there is any outgoing data to send. If there is, the ACK rides along with that data. If not, the ACK is sent on its own after the delay.

Without Delayed ACK
➑ Client sends data
β¬… Server sends ACK (separate packet)
β¬… Server sends response data (another packet)
2 packets from server ↑ overhead

With Delayed ACK (Piggybacking)
➑ Client sends data
⏳ Server waits up to 200ms
β¬… Server sends: ACK + response data (one packet)
1 packet from server ↓ less overhead
Every TCP segment has an ACK field β€” piggybacking uses it to avoid extra packets

Trade-off: Delayed ACK reduces the number of packets but adds a small delay. For interactive applications (like SSH), this can be noticeable. The TCP_NODELAY socket option (Nagle algorithm) can be used to disable this behavior.

πŸ’» Code Example: Observing ACK Behavior with TCP_NODELAY

The TCP_NODELAY socket option disables the Nagle algorithm, which is related to delayed ACK. When set, small segments are sent immediately rather than being buffered. This is important for real-time or low-latency applications.

/* tcp_nodelay_example.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>   /* for TCP_NODELAY */
#include <arpa/inet.h>

int main(void)
{
    int sockfd;
    int optval = 1;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) { perror("socket"); exit(EXIT_FAILURE); }

    /*
     * TCP_NODELAY: disables Nagle's algorithm
     * Without TCP_NODELAY: small writes may be buffered and batched together
     * With TCP_NODELAY: each write() sends a segment immediately
     *
     * Use when you need low latency (SSH, game servers, telemetry)
     * Avoid for bulk data transfer β€” Nagle reduces overhead there
     */
    if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
                   &optval, sizeof(optval)) == -1) {
        perror("setsockopt TCP_NODELAY");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    printf("TCP_NODELAY enabled β€” segments sent immediately\n");

    /* Check what value is set */
    socklen_t optlen = sizeof(optval);
    if (getsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
                   &optval, &optlen) == -1) {
        perror("getsockopt");
    } else {
        printf("TCP_NODELAY is currently: %s\n", optval ? "ON" : "OFF");
    }

    close(sockfd);
    return 0;
}
/* Checking RTO-related socket options */
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>

int main(void)
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    struct tcp_info info;
    socklen_t len = sizeof(info);

    if (getsockopt(sockfd, IPPROTO_TCP, TCP_INFO, &info, &len) == 0) {
        printf("RTT (smoothed): %u microseconds\n", info.tcpi_rtt);
        printf("RTT variance:   %u microseconds\n", info.tcpi_rttvar);
        printf("RTO:            %u microseconds\n", info.tcpi_rto);
        printf("Retransmits:    %u\n",               info.tcpi_retransmits);
    }

    close(sockfd);
    return 0;
}

Note: struct tcp_info and TCP_INFO are Linux-specific. They expose the TCP stack’s internal state for a socket β€” very useful for debugging network performance issues.

πŸ…Ύ Interview Questions β€” ACK, Retransmissions & Timeouts
Q1. What happens when a TCP segment is received with a checksum error?

The receiving TCP silently discards the segment. No ACK or NACK is sent. The sender detects the loss via the retransmission timer expiring and retransmits the segment.

Q2. What is RTO and how is it calculated?

RTO (Retransmission Timeout) is the time TCP waits for an ACK before retransmitting a segment. It is dynamically calculated using: RTO = SRTT + 4 Γ— RTTVAR, where SRTT is the smoothed RTT and RTTVAR is the RTT variance. This formula (from RFC 6298) adapts to network conditions.

Q3. What is Delayed ACK? What problem does it solve?

Delayed ACK is a technique where the receiver waits a short time (up to 200ms) before sending an ACK, to see if outgoing data can piggyback the ACK. It reduces the number of pure ACK packets in the network, lowering overhead and improving efficiency for bidirectional communication.

Q4. What is piggybacking in TCP?

Piggybacking is including an acknowledgement inside a data segment going in the opposite direction. Every TCP segment has an ACK field. Instead of sending a separate ACK packet, the receiver includes the ACK number in the next data packet it sends to the original sender. This halves the number of packets in a request-response pattern.

Q5. What is TCP_NODELAY and when would you use it?

TCP_NODELAY disables the Nagle algorithm, which batches small writes to reduce packet count. Use it when you need low-latency transmission (SSH, real-time game data, telemetry) and can’t afford the buffering delay. For bulk data transfers, keep Nagle enabled as it reduces overhead.

Q6. Can TCP retransmit a segment that was actually successfully received?

Yes. If the ACK was lost (not the data), the sender’s timer expires and it retransmits. The receiver may get a duplicate segment. TCP handles this by using sequence numbers to detect and discard duplicates silently.

Next: TCP Sequencing
Understand sequence numbers, ISN, in-order delivery, and duplicate elimination

Part 3 β†’ ← Part 1

Leave a Reply

Your email address will not be published. Required fields are marked *