RFC 793

Transmission Control Protocol

๐Ÿ“… published September 1981, from ietf

RFC 793: Transmission Control Protocol ๐ŸŽ€

Okay bestie, welcome to the legendary TCP spec ๐Ÿ’– Let's start with the title block tea โ˜•โœจ

The title is Transmission Control Protocol, part of the DARPA Internet Program Protocol Specification, and it's dated September 1981 ๐Ÿ“…. It was prepared for the Defense Advanced Research Projects Agency's Information Processing Techniques Office at 1400 Wilson Boulevard in Arlington, Virginia 22209, and the actual writing was done by the Information Sciences Institute at the University of Southern California, 4676 Admiralty Way, Marina del Rey, California 90291 ๐Ÿ›๏ธ. The editor is Jon Postel ๐Ÿ‘‘. This is the DoD Standard TCP, and it replaces RFC 761 ๐Ÿ”. The IEN documents numbered 129, 124, 112, 81, 55, 44, 40, 27, 21, and 5 are listed with it too ๐Ÿ“š.

Here's the table of contents, exactly as the original lays it out ๐Ÿ—บ๏ธ

    PREFACE ........................................................ iii

1.  INTRODUCTION ..................................................... 1

  1.1  Motivation .................................................... 1
  1.2  Scope ......................................................... 2
  1.3  About This Document ........................................... 2
  1.4  Interfaces .................................................... 3
  1.5  Operation ..................................................... 3

2.  PHILOSOPHY ....................................................... 7

  2.1  Elements of the Internetwork System ........................... 7
  2.2  Model of Operation ............................................ 7
  2.3  The Host Environment .......................................... 8
  2.4  Interfaces .................................................... 9
  2.5  Relation to Other Protocols ................................... 9
  2.6  Reliable Communication ........................................ 9
  2.7  Connection Establishment and Clearing ........................ 10
  2.8  Data Communication ........................................... 12
  2.9  Precedence and Security ...................................... 13
  2.10 Robustness Principle ......................................... 13

3.  FUNCTIONAL SPECIFICATION ........................................ 15

  3.1  Header Format ................................................ 15
  3.2  Terminology .................................................. 19
  3.3  Sequence Numbers ............................................. 24
  3.4  Establishing a connection .................................... 30
  3.5  Closing a Connection ......................................... 37
  3.6  Precedence and Security ...................................... 40
  3.7  Data Communication ........................................... 40
  3.8  Interfaces ................................................... 44
  3.9  Event Processing ............................................. 52

GLOSSARY ............................................................ 79

REFERENCES .......................................................... 85

PREFACE ๐Ÿ“œ

This document describes the DoD Standard Transmission Control Protocol (TCP) ๐Ÿ’…. There were nine earlier editions of the ARPA TCP spec, and this standard is built on them and borrows heavily from them ๐Ÿ™Œ. So many people contributed, both to the ideas and to the wording, which is honestly iconic. This edition clears up several details, gets rid of the end-of-letter buffer-size adjustments, and redescribes the letter mechanism as a push function โœจ.

Jon Postel Editor


1. INTRODUCTION ๐Ÿฆ‹

Okay, so TCP is meant to be a highly reliable host-to-host protocol ๐Ÿ’ช. It's for hosts talking to each other across packet-switched computer communication networks, and across interconnected systems made of those networks.

This doc explains the functions TCP performs, the program that implements it, and its interface to the programs or users that need its services ๐Ÿงฉ.

1.1. Motivation

Computer communication systems are playing a bigger and bigger role in military, government, and civilian settings ๐ŸŒ. This document focuses mostly on military computer communication needs, especially robustness when communication is unreliable and availability when there's congestion ๐Ÿ›ก๏ธ. But plenty of these problems show up in the civilian and government sectors too, so it's not just a military thing.

As strategic and tactical computer communication networks get developed and deployed, it's essential to connect them and to have standard interprocess communication protocols that can support a wide range of applications ๐Ÿ”—. Anticipating the need for those standards, the Deputy Undersecretary of Defense for Research and Engineering declared the TCP described here to be a basis for DoD-wide interprocess communication protocol standardization ๐Ÿ‘‘.

TCP is a connection-oriented, end-to-end reliable protocol ๐Ÿ’–. It's designed to sit in a layered hierarchy of protocols that support applications spanning multiple networks ๐Ÿฅž. It gives reliable interprocess communication between pairs of processes on host computers attached to separate but interconnected networks. Very few assumptions are made about how reliable the protocols below TCP are. TCP just assumes it can get a simple, potentially unreliable datagram service from the lower-level protocols ๐Ÿคทโ€โ™€๏ธ. In principle, TCP should be able to run on a wide range of communication systems, from hard-wired connections all the way up to packet-switched or circuit-switched networks ๐ŸŒˆ.

TCP is based on concepts first described by Cerf and Kahn in [1] ๐Ÿง . It fits into a layered protocol architecture just above the basic Internet Protocol [2] ๐Ÿฐ. That lower layer gives TCP a way to send and receive variable-length segments of information wrapped in internet datagram "envelopes" โœ‰๏ธ. The internet datagram is how source and destination TCPs in different networks get addressed. The internet protocol also handles any fragmentation or reassembly of TCP segments needed to get them through multiple networks and interconnecting gateways ๐Ÿšš. On top of that, it carries precedence, security classification, and compartmentation info for the TCP segments, so that information can travel end-to-end across multiple networks ๐Ÿ”.

                           Protocol Layering

                        +---------------------+
                        |     higher-level    |
                        +---------------------+
                        |        TCP          |
                        +---------------------+
                        |  internet protocol  |
                        +---------------------+
                        |communication network|
                        +---------------------+

                                Figure 1

Most of this document is written with TCP implementations in mind that live on the same host computer as the higher-level protocols ๐Ÿ . Some computer systems hook up to networks through front-end computers, which house the TCP and internet protocol layers along with network-specific software ๐Ÿ–ฅ๏ธ. The TCP spec describes an interface to the higher-level protocols that still seems implementable for the front-end case, as long as a suitable host-to-front-end protocol is in place ๐ŸŽฏ.

1.2. Scope

TCP is meant to provide a reliable process-to-process communication service in a multinetwork environment ๐Ÿ’ซ. It's also meant to be a host-to-host protocol in common use across multiple networks ๐ŸŒ.

1.3. About This Document

This document is the specification of the behavior required of any TCP implementation ๐Ÿ“‹. That covers both how it interacts with higher-level protocols and how it interacts with other TCPs ๐Ÿค. The rest of this section gives a very quick look at the protocol interfaces and how things operate. Section 2 sums up the philosophy behind the TCP design ๐Ÿง˜โ€โ™€๏ธ. Section 3 is the deep dive: a detailed description of what TCP has to do when different events happen (new segments arriving, user calls, errors, and so on), plus the exact formats of TCP segments ๐Ÿ”.

1.4. Interfaces

TCP talks to user or application processes on one side, and to a lower-level protocol like Internet Protocol on the other side ๐Ÿ”Œ.

The interface between an application process and TCP is shown in pretty good detail ๐Ÿ“ธ. It's a set of calls that feel a lot like the calls an operating system gives an application for handling files ๐Ÿ“. For example, there are calls to open and close connections, and calls to send and receive data on established connections. TCP is also expected to be able to talk to application programs asynchronously ๐Ÿ’ฌ. Implementors get a lot of freedom to design interfaces that suit their particular operating system environment, but a minimum level of functionality is required at the TCP/user interface for any valid implementation ๐Ÿซถ.

The interface between TCP and the lower-level protocol is basically unspecified, except that it's assumed some mechanism exists that lets the two layers pass information to each other asynchronously โšก. Usually the lower-level protocol is the one that specifies this interface. TCP is designed to work in a very general environment of interconnected networks, and the lower-level protocol assumed throughout this document is the Internet Protocol [2] ๐ŸŒธ.

Bestie, that's the end of part 1! ๐Ÿ’œ More parts are coming, starting with 1.5 Operation, so stay tuned ๐Ÿงš

1.5. Operation โœจ

okay so the main job of TCP is giving processes a reliable, securable logical circuit (aka a connection) with each other. ๐Ÿ”— Doing that on top of a less reliable internet system takes facilities in these areas:

  • Basic Data Transfer
  • Reliability
  • Flow Control
  • Multiplexing
  • Connections
  • Precedence and Security

Here's how TCP handles each one, bestie ๐Ÿ’…

Basic Data Transfer

TCP can move a continuous stream of octets in each direction between its users. It does this by packaging some octets into segments for transit through the internet system. Generally, the TCPs decide for themselves when to block up data and send it on, whatever works best for them ๐Ÿซถ

Sometimes users need to be sure that everything they handed to TCP actually got sent ๐Ÿ˜ญ That's what the push function is for. The sending user indicates that data should be pushed through to the receiving user, and a push makes the TCPs promptly forward and deliver the data up to that point. The exact push point might not be visible to the receiving user, and push doesn't add any record boundary marker either ๐ŸŽ€

Reliability

TCP must recover from data that is damaged, lost, duplicated, or delivered out of order by the internet communication system. ๐Ÿ”ฅ The way it does this is by giving every octet a sequence number and requiring a positive acknowledgment (ACK) from the receiving TCP. If the ACK doesn't arrive within a timeout interval, the data gets retransmitted. At the receiver, sequence numbers put segments that showed up out of order back in the right order and get rid of duplicates. Damage gets handled with a checksum on each segment, which the receiver checks, and damaged segments get discarded ๐Ÿงš

As long as the TCPs keep functioning properly and the internet system doesn't become completely partitioned, no transmission errors will mess with the correct delivery of data. TCP recovers from errors in the internet communication system, so it's giving resilient ๐Ÿ‘‘

Flow Control

TCP gives the receiver a way to control how much data the sender sends ๐ŸŒธ It does this by returning a "window" with every ACK. The window is a range of acceptable sequence numbers beyond the last segment successfully received. It tells the sender how many octets it may transmit before getting further permission. Main character energy for the receiver, honestly โœจ

Multiplexing

Lots of processes inside a single Host need to use TCP at the same time, so TCP provides a set of addresses called ports within each host ๐Ÿฆ‹ Put a port together with the network and host addresses from the internet communication layer and you get a socket. A pair of sockets uniquely identifies each connection. A single socket can be used in multiple connections at once, which is so iconic ๐Ÿ’œ

Each Host handles binding ports to processes on its own. It's useful, though, to attach commonly used processes (like a "logger" or a timesharing service) to fixed sockets that are published to the public. Then people can reach those services through the known addresses. Finding out about other processes' ports can involve more dynamic mechanisms ๐Ÿ“

Connections

The reliability and flow control mechanisms we just talked about need TCPs to set up and keep track of certain status information for each data stream. That whole bundle, which includes sockets, sequence numbers, and window sizes, is called a connection ๐ŸŽ€ Each connection is uniquely specified by a pair of sockets identifying its two sides.

When two processes want to talk, their TCPs must first set up a connection (initializing the status information on each side) ๐Ÿซถ When they're done, the connection gets terminated or closed so the resources can be freed up for other stuff.

Connections have to be set up between unreliable hosts over an unreliable internet communication system, so TCP uses a handshake mechanism with clock-based sequence numbers. This avoids erroneous initialization of connections. It's giving security guard energy ๐Ÿ™ˆ

Precedence and Security

TCP users can indicate the security and precedence of their communication ๐Ÿ” Default values are provided for when these features aren't needed, so you're never stuck picking โœจ

2. PHILOSOPHY ๐Ÿง 

2.1. Elements of the Internetwork System

The internetwork environment is made of hosts connected to networks, and those networks are interconnected via gateways ๐ŸŒˆ Here it's assumed the networks could be local networks (like the ETHERNET) or large networks (like the ARPANET), but either way they're based on packet switching technology. The active agents that produce and consume messages are processes. Various levels of protocols in the networks, the gateways, and the hosts work together to support an interprocess communication system. That system gives two-way data flow on logical connections between process ports ๐Ÿ’–

The word packet is used generically to mean the data of one transaction between a host and its network. We're generally not going to worry about the format of the data blocks exchanged within a network, since that's not our problem ๐Ÿ™ˆ

Hosts are computers attached to a network. From the communication network's point of view, they're the sources and destinations of packets. Processes are the active elements in host computers (a process being a program in execution, which is the pretty common definition). Even terminals, files, and other I/O devices communicate with each other through processes. So all communication is really inter-process communication ๐Ÿฆ‹

Since a process might need to tell apart several communication streams between itself and another process (or several processes), we picture each process as having a number of ports it uses to talk to other processes' ports ๐Ÿงš

2.2. Model of Operation

Processes send data by calling on TCP and passing it buffers of data as arguments ๐Ÿ’Œ TCP packages the data from those buffers into segments and calls on the internet module to transmit each segment to the destination TCP. The receiving TCP puts the data from a segment into the receiving user's buffer and then notifies that user. The TCPs put control information in the segments, which they use to make sure data is transmitted reliably and in order ๐Ÿ”ฅ

The model of internet communication has an internet protocol module tied to each TCP, and it provides an interface to the local network. This internet module packages TCP segments inside internet datagrams and routes those datagrams to a destination internet module or an intermediate gateway. To send the datagram through the local network, it gets embedded in a local network packet ๐Ÿ“ฆ

The packet switches may perform further packaging, fragmentation, or other operations to get the local packet delivered to the destination internet module ๐ŸŒธ

At a gateway between networks, the internet datagram gets "unwrapped" from its local packet and examined to figure out which network it should travel through next. Then it gets "wrapped" in a local packet that suits the next network and routed onward, either to the next gateway or to the final destination โœจ

A gateway is permitted to break an internet datagram into smaller internet datagram fragments when that's needed for transmission through the next network. To do this, the gateway produces a set of internet datagrams, each carrying one fragment. Fragments can be broken down even further at later gateways. The internet datagram fragment format is designed so the destination internet module can reassemble the fragments into internet datagrams ๐Ÿงฉ

A destination internet module unwraps the segment from the datagram (reassembling the datagram first, if necessary) and passes the segment to the destination TCP ๐Ÿ’œ

This simple model glosses over a lot of details ๐Ÿ™ˆ One important feature is the type of service. It gives the gateway (or internet module) information to guide it in choosing the service parameters for traversing the next network. The type of service information includes the precedence of the datagram. Datagrams can also carry security information, so hosts and gateways operating in multilevel secure environments can properly segregate datagrams for security reasons ๐Ÿ”

2.3. The Host Environment

TCP is assumed to be a module inside an operating system ๐Ÿ–ฅ๏ธ Users access TCP pretty much the way they'd access the file system. TCP may call on other operating system functions, for example to manage its data structures. The actual interface to the network is assumed to be controlled by a device driver module. TCP doesn't call the network device driver directly. Instead, it calls the internet datagram protocol module, which may in turn call the device driver ๐Ÿซถ

The TCP mechanisms don't rule out implementing TCP in a front-end processor. However, in that kind of implementation, a host-to-front-end protocol must provide the functionality needed to support the type of TCP-user interface described in this document ๐ŸŽ€

2.4. Interfaces

The TCP/user interface lets the user call TCP to OPEN or CLOSE a connection, to SEND or RECEIVE data, or to get STATUS about a connection ๐Ÿ“ž These calls work like other calls from user programs on the operating system, like the calls to open, read from, and close a file ๐Ÿ“

The TCP/internet interface provides calls to send and receive datagrams addressed to TCP modules in hosts anywhere in the internet system. These calls have parameters for passing the address, type of service, precedence, security, and other control information ๐ŸŒ

2.5. Relation to Other Protocols

Here's a diagram showing where TCP sits in the protocol hierarchy ๐Ÿฆ‹

     +------+ +-----+ +-----+       +-----+
     |Telnet| | FTP | |Voice|  ...  |     |  Application Level
     +------+ +-----+ +-----+       +-----+
           |   |         |             |
          +-----+     +-----+       +-----+
          | TCP |     | RTP |  ...  |     |  Host Level
          +-----+     +-----+       +-----+
             |           |             |
          +-------------------------------+
          |    Internet Protocol & ICMP   |  Gateway Level
          +-------------------------------+
                         |
            +---------------------------+
            |   Local Network Protocol  |    Network Level
            +---------------------------+

                       Protocol Relationships

                             Figure 2.

TCP is expected to be able to support higher level protocols efficiently ๐Ÿ’ช It should be easy to interface higher level protocols like the ARPANET Telnet or AUTODIN II THP to TCP ๐ŸŒŸ

2.6. Reliable Communication ๐Ÿ’–

okay so the big promise here is that a stream of data sent on a TCP connection gets delivered reliably and in order at the destination ๐Ÿซถโœจ no lost puzzle pieces, no shuffled pages, periodt.

the way TCP pulls this off is with sequence numbers and acknowledgments. Conceptually, every single octet of data gets its own sequence number ๐Ÿ”ข The sequence number of the first octet in a segment rides along with that segment and gets called the segment sequence number. Segments also carry an acknowledgment number, which is the sequence number of the next data octet the sender is expecting to receive in the reverse direction. so it's basically a little "got everything up to here, send me the next one" note ๐Ÿ’Œ

here's the retransmission dance ๐Ÿ’ƒ When TCP sends a segment with data, it puts a copy on a retransmission queue and starts a timer โฐ Once the acknowledgment for that data shows up, the segment gets deleted from the queue. But if the timer runs out before the ack arrives, the segment gets sent again ๐Ÿ” iconic persistence honestly.

ngl this part is easy to misread: an acknowledgment from TCP does not mean the data reached the end user ๐Ÿ™ˆ It only means the receiving TCP has taken responsibility for delivering it. big difference, bestie!

now for flow control ๐ŸŒธ To keep the data flowing at a sane pace between TCPs, the receiving TCP reports a "window" to the sending TCP. That window tells the sender how many octets, counting from the acknowledgment number, the receiver is currently ready to take. it's giving "here's how much room I have right now" energy ๐Ÿ›๏ธ๐Ÿ’…


2.7. Connection Establishment and Clearing ๐Ÿฆ‹

so TCP needs a way to keep all its separate data streams apart, and that's where the port identifier comes in ๐ŸŽ€ Each TCP picks its ports independently, which means two TCPs might pick the same port number. Not unique! So to make things unique across the whole thing, we glue an internet address (the one identifying the TCP) onto a port identifier. That combo is called a socket, and it's unique across every network connected together ๐ŸŒ๐Ÿ‘‘

a connection is fully defined by the pair of sockets at its two ends. One local socket can be part of a bunch of connections, each going to a different foreign socket ๐Ÿงš And connections are full duplex, which just means data can flow in both directions at once โ†”๏ธโœจ

TCPs get to decide how they link ports to processes ๐Ÿ’… That said, every implementation needs a few basic ideas. There have to be well-known sockets that the TCP only hands out to the "appropriate" processes, somehow. The vibe is that processes can own ports, and a process can only start connections on ports it owns ๐Ÿ” (How you do the ownership bit is a local business, but the spec imagines a Request Port user command, or a way to hand out a whole group of ports to one process, like using the high-order bits of a port name to mark which process owns it.)

when a connection gets opened, the OPEN call takes a local port and a foreign socket. In return, the TCP gives back a short local connection name that the user can use in later calls ๐Ÿ“‡ Plenty of info about each connection has to be remembered, so we imagine a data structure called a Transmission Control Block (TCB) ๐Ÿ—‚๏ธ One way to build it is to make the local connection name just a pointer to that connection's TCB. The OPEN call also says whether the connection should be actively pursued or passively waited for ๐Ÿ‘€

a passive OPEN means the process wants to accept incoming connection requests instead of starting one itself ๐Ÿšช A lot of the time, a passive OPEN will take a connection from anybody ๐Ÿ™Œ For that case, a foreign socket of all zeros stands for "unspecified." Unspecified foreign sockets are only allowed on passive OPENs, so no sneaking them into active ones ๐Ÿ™…โ€โ™€๏ธ

picture a service process that wants to help unknown processes ๐Ÿค It would issue a passive OPEN with an unspecified foreign socket, and then any process that asks to connect to that local socket can get in. it helps a lot if everyone knows that local socket belongs to this service ๐Ÿ“ฃ

well-known sockets are a neat shortcut for tying a socket address to a standard service ๐ŸŒŸ For example, the "Telnet-Server" process is permanently pinned to one particular socket. Other sockets are set aside for File Transfer, Remote Job Entry, Text Generator, Echoer, and Sink processes (the last three are just for testing ๐Ÿงช). There could even be a socket reserved for a "Look-Up" service, which would tell you which specific socket a newly created service is available on ๐Ÿ” The well-known socket idea is part of TCP, but which services get which sockets is outside this spec (see [4]).

processes can issue passive OPENs, sit there waiting for matching active OPENs, and get told by TCP when a connection is established ๐Ÿ”” Two processes that issue active OPENs to each other at the same time still get connected correctly ๐Ÿคฏ That flexibility is a big deal for distributed computing, where components do their own thing asynchronously ๐Ÿ’œ

there are two main ways a local passive OPEN can match a foreign active OPEN. In the first, the passive OPEN fully specified the foreign socket, so the match has to be exact ๐ŸŽฏ In the second, the passive OPEN left the foreign socket unspecified, so any foreign socket works as long as the local sockets match โœ… Partially restricted matches are possible too, so there's wiggle room ๐Ÿ“

now, if several pending passive OPENs (saved in TCBs) share the same local socket, a foreign active OPEN gets matched first to a TCB that names that exact foreign socket, if one exists ๐Ÿฅ‡ Only after that does it look at a TCB with an unspecified foreign socket ๐Ÿฅˆ

establishing a connection uses the synchronize (SYN) control flag and a three-message exchange ๐Ÿค People call this the three-way handshake [3] ๐Ÿ’–

a connection starts when an arriving segment with a SYN meets a waiting TCB entry, and both came from user OPEN commands ๐Ÿ’ซ When the local and foreign sockets match, that's when the connection counts as initiated. It becomes "established" once sequence numbers have been synchronized in both directions ๐ŸŽ‰

clearing a connection also takes a few segments, but this time they carry the FIN control flag ๐Ÿ‘‹


2.8. Data Communication ๐Ÿ“ฎ

the data on a connection can be pictured as a stream of octets ๐ŸŒŠ With each SEND call, the sending user says whether that data (and any earlier data) should be pushed straight through to the receiving user, by setting the PUSH flag ๐Ÿš€

the sending TCP is allowed to collect data from the sending user and send it in segments whenever it's convenient for it ๐Ÿ•ฐ๏ธ But once the push function gets signaled, it must send all the unsent data. And when a receiving TCP sees the PUSH flag, it must not wait for more data from the sending TCP before handing the data to the receiving process ๐Ÿƒโ€โ™€๏ธ๐Ÿ’จ

heads up, bestie: there's no required link between push and segment boundaries ๐Ÿ™ˆ A segment's data might come from one SEND call (all of it or just part of it), or it might come from several SEND calls mashed together.

the whole point of the push function and PUSH flag is to get data through from the sending user to the receiving user ๐Ÿ’• It is not a record service. Don't go looking for message boundaries here ๐Ÿ™…โ€โ™€๏ธ

there's also a link between the push function and the buffers that cross the TCP/user interface ๐Ÿงบ Every time a PUSH flag goes with data placed into the receiving user's buffer, that buffer gets handed back to the user for processing, even if it isn't full yet ๐Ÿ“ค And if data fills up the user's buffer before a PUSH shows up, the data gets passed along in buffer-size chunks ๐Ÿ“ฆ

TCP also has a way to tell the receiver that, further along in the data stream than what the receiver is currently reading, there's urgent data ๐Ÿšจ TCP doesn't dictate what the user does once it hears about pending urgent data. The general idea is that the receiving process takes action to process that urgent data quickly โšก


2.9. Precedence and Security ๐Ÿ”’

TCP uses the internet protocol type of service field and the security option to offer precedence and security on a per-connection basis to TCP users ๐Ÿ‘‘ Not every TCP module will work in a multilevel secure environment. Some might be limited to unclassified use only, and others might only run at one security level and compartment ๐Ÿง So some TCP implementations, and the services they offer users, may only cover a subset of the multilevel secure case ๐Ÿซง

TCP modules that do operate in a multilevel secure environment must properly mark outgoing segments with the security, compartment, and precedence ๐Ÿท๏ธ Those modules also must give their users, or higher level protocols like Telnet or THP, an interface for specifying the security level, compartment, and precedence they want for connections ๐ŸŒˆ


2.10. Robustness Principle ๐Ÿ›ก๏ธ

TCP implementations follow a general principle of robustness, and it's the iconic one: be conservative in what you do, be liberal in what you accept from others ๐Ÿ’…โœจ Send carefully, receive generously, always. that's the energy ๐Ÿซถ

3. FUNCTIONAL SPECIFICATION โœจ

3.1. Header Format โœจ

okay so TCP segments get sent as internet datagrams ๐Ÿ“ฆ the IP header carries a bunch of info, including the source and destination host addresses [2]. then the TCP header comes right after the internet header and holds all the TCP-specific stuff ๐ŸŽ€ this split is lowkey genius bc it means other host-level protocols can exist alongside TCP ๐Ÿซถ

TCP Header Format

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Source Port          |       Destination Port        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Sequence Number                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Acknowledgment Number                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Checksum            |         Urgent Pointer        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                            TCP Header Format

Note that one tick mark represents one bit position. ๐Ÿ”

Figure 3. ๐Ÿฆ‹

Source Port: 16 bits ๐ŸŒธ

The source port number. ๐Ÿ’–

Destination Port: 16 bits ๐ŸŒธ

The destination port number. ๐Ÿ’–

Sequence Number: 32 bits ๐Ÿงš

The sequence number of the first data octet in this segment (except when SYN is present). If SYN is present the sequence number is the initial sequence number (ISN) and the first data octet is ISN+1. ๐Ÿซถ

Acknowledgment Number: 32 bits ๐Ÿงš

If the ACK control bit is set this field contains the value of the next sequence number the sender of the segment is expecting to receive. Once a connection is established this is always sent. ๐Ÿ’…

Data Offset: 4 bits ๐Ÿ“

The number of 32 bit words in the TCP Header. This indicates where the data begins. The TCP header (even one including options) is an integral number of 32 bits long. โœจ

Reserved: 6 bits ๐Ÿ™ˆ

Reserved for future use. MUST be zero. ๐Ÿšซ

Control Bits: 6 bits (from left to right): ๐ŸŽ›๏ธ

  • URG: Urgent Pointer field significant ๐Ÿ”ฅ
  • ACK: Acknowledgment field significant ๐Ÿ’œ
  • PSH: Push Function ๐ŸŒˆ
  • RST: Reset the connection ๐Ÿ’€
  • SYN: Synchronize sequence numbers ๐Ÿ‘‘
  • FIN: No more data from sender ๐Ÿ“

Window: 16 bits ๐ŸชŸ

The number of data octets beginning with the one indicated in the acknowledgment field which the sender of this segment is willing to accept. ๐ŸŒท

Checksum: 16 bits ๐Ÿงฎ

The checksum field is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header and text. If a segment contains an odd number of header and text octets to be checksummed, the last octet is padded on the right with zeros to form a 16 bit word for checksum purposes. The pad is not transmitted as part of the segment. While computing the checksum, the checksum field itself is replaced with zeros. ๐Ÿค“

The checksum also covers a 96 bit pseudo header conceptually prefixed to the TCP header. This pseudo header contains the Source Address, the Destination Address, the Protocol, and TCP length. This gives the TCP protection against misrouted segments. This information is carried in the Internet Protocol and is transferred across the TCP/Network interface in the arguments or results of calls by the TCP on the IP. ๐Ÿ—บ๏ธ

                     +--------+--------+--------+--------+
                     |           Source Address          |
                     +--------+--------+--------+--------+
                     |         Destination Address       |
                     +--------+--------+--------+--------+
                     |  zero  |  PTCL  |    TCP Length   |
                     +--------+--------+--------+--------+

The TCP Length is the TCP header length plus the data length in octets (this is not an explicitly transmitted quantity, but is computed), and it does not count the 12 octets of the pseudo header. ๐Ÿง 

Urgent Pointer: 16 bits ๐Ÿšจ

This field communicates the current value of the urgent pointer as a positive offset from the sequence number in this segment. The urgent pointer points to the sequence number of the octet following the urgent data. This field is only be interpreted in segments with the URG control bit set. ๐ŸŽฏ

Options: variable โš™๏ธ

Options may occupy space at the end of the TCP header and are a multiple of 8 bits in length. All options are included in the checksum. An option may begin on any octet boundary. There are two cases for the format of an option: ๐ŸŽ€

  • Case 1: A single octet of option-kind.
  • Case 2: An octet of option-kind, an octet of option-length, and the actual option-data octets.

The option-length counts the two octets of option-kind and option-length as well as the option-data octets. ๐Ÿ”ข

Note that the list of options may be shorter than the data offset field might imply. The content of the header beyond the End-of-Option option MUST be header padding (i.e., zero). ๐Ÿซง

A TCP MUST implement all options. ๐Ÿ”ฅ๐Ÿ”ฅ

Currently defined options include (kind indicated in octal): ๐Ÿ“‹

  Kind     Length    Meaning
  ----     ------    -------
   0         -       End of option list.
   1         -       No-Operation.
   2         4       Maximum Segment Size.

Specific Option Definitions ๐Ÿญ

End of Option List ๐Ÿ›‘

    +--------+
    |00000000|
    +--------+
     Kind=0

This option code indicates the end of the option list. This might not coincide with the end of the TCP header according to the Data Offset field. This is used at the end of all options, not the end of each option, and need only be used if the end of the options would not otherwise coincide with the end of the TCP header. ๐Ÿงฉ

No-Operation ๐Ÿ˜ถโ€๐ŸŒซ๏ธ

    +--------+
    |00000001|
    +--------+
     Kind=1

This option code MAY be used between options, for example, to align the beginning of a subsequent option on a word boundary. There is no guarantee that senders will use this option, so receivers MUST be prepared to process options even if they do not begin on a word boundary. ๐Ÿคทโ€โ™€๏ธ

Maximum Segment Size ๐Ÿ“

    +--------+--------+---------+--------+
    |00000010|00000100|   max seg size   |
    +--------+--------+---------+--------+
     Kind=2   Length=4

Maximum Segment Size Option Data: 16 bits ๐Ÿ’Ž

If this option is present, then it communicates the maximum receive segment size at the TCP which sends this segment. This field MUST only be sent in the initial connection request (i.e., in segments with the SYN control bit set). If this option is not used, any segment size is allowed. ๐ŸŒŸ

Padding: variable ๐Ÿซง

The TCP header padding is used to ensure that the TCP header ends and data begins on a 32 bit boundary. The padding is composed of zeros. ๐Ÿค

3.2. Terminology โœจ

okay bestie, before we can talk about how TCP actually works ๐Ÿง  we need some vocab, no cap. TCP has to remember a bunch of stuff about each connection, so we put all of it in one record called a Transmission Control Block, or TCB ๐Ÿ“ฆ ๐ŸŽ€. Inside the TCB you'll find the local and remote socket numbers, the security and precedence of the connection, pointers to the user's send and receive buffers, pointers to the retransmit queue and to the current segment. On top of that, a bunch of sequence number variables live in there too, and they're the main characters of this whole section ๐Ÿ’…

Send Sequence Variables

Here's the send side crew ๐Ÿ’–

  • SND.UNA - send unacknowledged
  • SND.NXT - send next
  • SND.WND - send window
  • SND.UP - send urgent pointer
  • SND.WL1 - segment sequence number used for last window update
  • SND.WL2 - segment acknowledgment number used for last window update
  • ISS - initial send sequence number

Receive Sequence Variables

And now the receive side ๐Ÿฆ‹

  • RCV.NXT - receive next
  • RCV.WND - receive window
  • RCV.UP - receive urgent pointer
  • IRS - initial receive sequence number

These diagrams help you picture how those variables map onto the sequence space, and honestly they're iconic ๐Ÿคฉ

Send Sequence Space

                 1         2          3          4
            ----------|----------|----------|----------
                   SND.UNA    SND.NXT    SND.UNA
                                        +SND.WND

      1 - old sequence numbers which have been acknowledged
      2 - sequence numbers of unacknowledged data
      3 - sequence numbers allowed for new data transmission
      4 - future sequence numbers which are not yet allowed

                        Send Sequence Space

                             Figure 4.

The send window is the portion of the sequence space labeled 3 in figure 4 ๐Ÿ’œ

Receive Sequence Space

                     1          2          3
                 ----------|----------|----------
                        RCV.NXT    RCV.NXT
                                  +RCV.WND

      1 - old sequence numbers which have been acknowledged
      2 - sequence numbers allowed for new reception
      3 - future sequence numbers which are not yet allowed

                       Receive Sequence Space

                             Figure 5.

The receive window is the portion of the sequence space labeled 2 in figure 5 ๐ŸŒธ

There are also some variables that get their values from the fields of the current segment, so they're basically the segment's own little ID card ๐Ÿชช

Current Segment Variables

  • SEG.SEQ - segment sequence number
  • SEG.ACK - segment acknowledgment number
  • SEG.LEN - segment length
  • SEG.WND - segment window
  • SEG.UP - segment urgent pointer
  • SEG.PRC - segment precedence value

A connection moves through a series of states over its whole lifetime ๐ŸŒˆ The states are: LISTEN, SYN-SENT, SYN-RECEIVED, ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT, and the fictional state CLOSED. ๐Ÿ™ˆ CLOSED is fictional because it means there's no TCB, and therefore no connection at all. Here's the quick tea on each one:

  • LISTEN - waiting for a connection request from any remote TCP and port ๐Ÿ‘‚
  • SYN-SENT - waiting for a matching connection request after having sent a connection request ๐Ÿ“ค
  • SYN-RECEIVED - waiting for a confirming connection request acknowledgment, after having both received and sent a connection request ๐Ÿค
  • ESTABLISHED - an open connection where data received can be delivered to the user. This is the normal state for the data transfer phase of the connection โœจ
  • FIN-WAIT-1 - waiting for a connection termination request from the remote TCP, or an acknowledgment of the termination request you already sent ๐Ÿ‘‹
  • FIN-WAIT-2 - waiting for a connection termination request from the remote TCP ๐Ÿฅฑ
  • CLOSE-WAIT - waiting for a connection termination request from the local user ๐Ÿ™‹
  • CLOSING - waiting for a connection termination request acknowledgment from the remote TCP ๐Ÿ˜ฌ
  • LAST-ACK - waiting for an acknowledgment of the connection termination request you previously sent to the remote TCP (which includes an acknowledgment of its connection termination request) ๐Ÿซ 
  • TIME-WAIT - waiting for enough time to pass to be sure the remote TCP received the acknowledgment of its connection termination request โณ
  • CLOSED - no connection state at all ๐Ÿซฅ

A TCP connection hops from one state to another in response to events โšก The events are the user calls OPEN, SEND, RECEIVE, CLOSE, ABORT, and STATUS; the incoming segments, especially the ones carrying the SYN, ACK, RST and FIN flags; and timeouts โฐ

Figure 6 is the state diagram. It only shows state changes, plus the events that cause them and the resulting actions. It doesn't cover error conditions or actions that aren't tied to a state change, but we get more into that later ๐Ÿ”

NOTE BENE: this diagram is only a summary and must not be taken as the total specification. Don't treat it like the full rulebook, bestie ๐Ÿšซ๐Ÿ“–
                          +---------+ ---------\      active OPEN
                          |  CLOSED |            \    -----------
                          +---------+<---------\   \   create TCB
                            |     ^              \   \  snd SYN
               passive OPEN |     |   CLOSE        \   \
               ------------ |     | ----------       \   \
                create TCB  |     | delete TCB         \   \
                            V     |                      \   \
                          +---------+            CLOSE    |    \
                          |  LISTEN |          ---------- |     |
                          +---------+          delete TCB |     |
               rcv SYN      |     |     SEND              |     |
              -----------   |     |    -------            |     V
 +---------+      snd SYN,ACK  /       \   snd SYN          +---------+
 |         |<-----------------           ------------------>|         |
 |   SYN   |                    rcv SYN                     |   SYN   |
 |   RCVD  |<-----------------------------------------------|   SENT  |
 |         |                    snd ACK                     |         |
 |         |------------------           -------------------|         |
 +---------+   rcv ACK of SYN  \       /  rcv SYN,ACK       +---------+
   |           --------------   |     |   -----------
   |                  x         |     |     snd ACK
   |                            V     V
   |  CLOSE                   +---------+
   | -------                  |  ESTAB  |
   | snd FIN                  +---------+
   |                   CLOSE    |     |    rcv FIN
   V                  -------   |     |    -------
 +---------+          snd FIN  /       \   snd ACK          +---------+
 |  FIN    |<-----------------           ------------------>|  CLOSE  |
 | WAIT-1  |------------------                              |   WAIT  |
 +---------+          rcv FIN  \                            +---------+
   | rcv ACK of FIN   -------   |                            CLOSE  |
   | --------------   snd ACK   |                           ------- |
   V        x                   V                           snd FIN V
 +---------+                  +---------+                   +---------+
 |FINWAIT-2|                  | CLOSING |                   | LAST-ACK|
 +---------+                  +---------+                   +---------+
   |                rcv ACK of FIN |                 rcv ACK of FIN |
   |  rcv FIN       -------------- |    Timeout=2MSL -------------- |
   |  -------              x       V    ------------        x       V
    \ snd ACK                 +---------+delete TCB         +---------+
     ------------------------>|TIME WAIT|------------------>| CLOSED  |
                              +---------+                   +---------+

                      TCP Connection State Diagram
                               Figure 6.

3.3. Sequence Numbers ๐Ÿ”ข๐Ÿ’•

okay this is the big one, so get comfy ๐Ÿ›‹๏ธ A fundamental idea in TCP's design is that every octet of data sent over a TCP connection gets its own sequence number ๐ŸŽฏ Since every octet is numbered, each one can be acknowledged. The acknowledgment mechanism is cumulative: an acknowledgment of sequence number X means that all octets up to but not including X have been received โœ… This makes duplicate detection straightforward when retransmissions happen, which is so smart ๐Ÿง โœจ Within a segment, the first data octet right after the header is the lowest numbered, and the octets after it are numbered consecutively ๐Ÿ“š

Now the sequence number space is finite, even though it's super huge ๐ŸŒŒ It goes from 0 to 2**32 - 1. Since it's finite, all arithmetic on sequence numbers MUST be done modulo 2**32. This unsigned arithmetic keeps the relationships between sequence numbers intact as they wrap around from 2**32 - 1 back to 0 ๐Ÿ”„ There are some subtleties to modular arithmetic, so take great care when you program comparisons of these values ๐Ÿ’€ The symbol "=<" means "less than or equal" (modulo 2**32) ๐Ÿงฎ

The typical kinds of sequence number comparisons TCP has to do include:

  1. Determining that an acknowledgment refers to some sequence number that was sent but not yet acknowledged ๐Ÿ‘€
  2. Determining that all sequence numbers occupied by a segment have been acknowledged (for example, to remove the segment from a retransmission queue) ๐Ÿ—‘๏ธ
  3. Determining that an incoming segment contains sequence numbers that are expected (in other words, the segment "overlaps" the receive window) ๐ŸชŸ

When you send data, TCP is going to receive acknowledgments back. These comparisons are needed to process those acknowledgments ๐Ÿ“ฌ

SND.UNA = oldest unacknowledged sequence number

SND.NXT = next sequence number to be sent

SEG.ACK = acknowledgment from the receiving TCP (next sequence
          number expected by the receiving TCP)

SEG.SEQ = first sequence number of a segment

SEG.LEN = the number of octets occupied by the data in the segment
          (counting SYN and FIN)

SEG.SEQ+SEG.LEN-1 = last sequence number of a segment

A new acknowledgment (called an "acceptable ack") is one where this inequality holds:

SND.UNA < SEG.ACK =< SND.NXT

A segment on the retransmission queue is fully acknowledged if the sum of its sequence number and length is less than or equal to the acknowledgment value in the incoming segment ๐ŸŽ‰

When data comes in, these comparisons are needed too ๐Ÿ“ฅ

RCV.NXT = next sequence number expected on an incoming segments, and
    is the left or lower edge of the receive window

RCV.NXT+RCV.WND-1 = last sequence number expected on an incoming
    segment, and is the right or upper edge of the receive window

SEG.SEQ = first sequence number occupied by the incoming segment

SEG.SEQ+SEG.LEN-1 = last sequence number occupied by the incoming
    segment

A segment counts as occupying a portion of valid receive sequence space if either of these is true ๐Ÿฆ‹

RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND

or

RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND

The first part of this test checks whether the start of the segment falls in the window, and the second part checks whether the end of the segment falls in the window. If the segment passes either part, it contains data in the window ๐Ÿ’…

Actually, it's a little more complicated than that ๐Ÿ™ˆ Because of zero windows and zero length segments, there are four cases for whether an incoming segment is acceptable ๐Ÿฆ‹

  Segment Receive  Test
  Length  Window
  ------- -------  -------------------------------------------

     0       0     SEG.SEQ = RCV.NXT

     0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND

    >0       0     not acceptable

    >0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
                or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND

Note that when the receive window is zero, no segments should be acceptable except ACK segments. So it is possible for a TCP to maintain a zero receive window while transmitting data and receiving ACKs ๐ŸŒธ However, even when the receive window is zero, a TCP must process the RST and URG fields of all incoming segments ๐Ÿซถ

We also used the numbering scheme to protect certain control information โœจ The trick is that some control flags get implicitly included in the sequence space, so they can be retransmitted and acknowledged without confusion. (Basically, one and only one copy of the control gets acted upon. Iconic.) Control information is not physically carried in the segment data space, so we need rules for implicitly assigning sequence numbers to control ๐ŸŽ€ The SYN and FIN are the only controls that need this protection, and they're only used at connection opening and closing ๐Ÿ”ฅ

For sequence number purposes, the SYN is considered to occur before the first actual data octet of the segment it's in, while the FIN is considered to occur after the last actual data octet in the segment it's in. The segment length (SEG.LEN) includes both data and sequence space occupying controls. When a SYN is present, SEG.SEQ is the sequence number of the SYN ๐Ÿงš

Initial Sequence Number Selection โœจ

The protocol places no restriction on a particular connection being used over and over again ๐Ÿ“ A connection is defined by a pair of sockets, and new instances of a connection are called incarnations of the connection. The problem is: "how does the TCP identify duplicate segments from previous incarnations of the connection?" ๐Ÿ’€ This gets very real if the connection is opened and closed in quick succession, or if the connection breaks with loss of memory and is then reestablished ๐Ÿ˜ญ

To avoid confusion, we must prevent segments from one incarnation of a connection from being used while the same sequence numbers may still be floating around the network from an earlier incarnation. We want to make sure of this even if a TCP crashes and loses all knowledge of the sequence numbers it has been using ๐Ÿ‘‘ When new connections are created, an initial sequence number (ISN) generator is employed, and it selects a new 32 bit ISN. The generator is bound to a (possibly fictitious) 32 bit clock whose low order bit is incremented roughly every 4 microseconds. So the ISN cycles approximately every 4.55 hours. Since we assume segments will stay in the network no more than the Maximum Segment Lifetime (MSL), and the MSL is less than 4.55 hours, we can reasonably assume ISNs will be unique ๐ŸŒˆ

For each connection there's a send sequence number and a receive sequence number. The initial send sequence number (ISS) is chosen by the data sending TCP, and the initial receive sequence number (IRS) is learned during the connection establishing procedure ๐Ÿ’œ

For a connection to be established or initialized, the two TCPs must synchronize on each other's initial sequence numbers. This happens in an exchange of connection establishing segments carrying a control bit called "SYN" (for synchronize) along with the initial sequence numbers. As a shorthand, segments carrying the SYN bit are also called "SYNs". So the solution needs a suitable mechanism for picking an initial sequence number, plus a slightly involved handshake to exchange the ISNs ๐Ÿฆ‹

The synchronization requires each side to send its own initial sequence number and to receive a confirmation of it in an acknowledgment from the other side. Each side must also receive the other side's initial sequence number and send a confirming acknowledgment ๐Ÿซถ

  1) A --> B  SYN my sequence number is X
  2) A <-- B  ACK your sequence number is X
  3) A <-- B  SYN my sequence number is Y
  4) A --> B  ACK your sequence number is Y

Because steps 2 and 3 can be combined in a single message, this is called the three way (or three message) handshake ๐ŸŽ€

A three way handshake is necessary because sequence numbers are not tied to a global clock in the network, and TCPs may have different mechanisms for picking the ISNs ๐Ÿ™ˆ The receiver of the first SYN has no way of knowing whether the segment was an old delayed one or not, unless it remembers the last sequence number used on the connection (which is not always possible). So it must ask the sender to verify this SYN. The three way handshake and the advantages of a clock-driven scheme are discussed in [3] ๐Ÿ“š

Knowing When to Keep Quiet ๐Ÿคซ

To be sure that a TCP doesn't create a segment carrying a sequence number that an old segment still in the network might duplicate, the TCP must keep quiet for a maximum segment lifetime (MSL) before assigning any sequence numbers. This applies upon starting up or recovering from a crash in which memory of the sequence numbers in use was lost ๐Ÿ˜ญ For this specification, the MSL is taken to be 2 minutes. This is an engineering choice, and it may be changed if experience indicates it's desirable to do so ๐Ÿ’…

Note that if a TCP is reinitialized in some sense, yet retains its memory of sequence numbers in use, then it need not wait at all. It only has to be sure to use sequence numbers larger than those recently used โœจ

The TCP Quiet Time Concept ๐Ÿงš

This specification provides that hosts which "crash" without retaining any knowledge of the last sequence numbers transmitted on each active (i.e., not closed) connection shall delay emitting any TCP segments for at least the agreed Maximum Segment Lifetime (MSL) in the internet system of which the host is a part. In the paragraphs below, an explanation for this specification is given. TCP implementors may violate the "quiet time" restriction, but only at the risk of causing some old data to be accepted as new, or new data to be rejected as old, duplicated by some receivers in the internet system ๐ŸŒˆ

TCPs consume sequence number space each time a segment is formed and entered into the network output queue at a source host. The duplicate detection and sequencing algorithm in the TCP protocol relies on the unique binding of segment data to sequence space, to the extent that sequence numbers will not cycle through all 2**32 values before the segment data bound to those sequence numbers has been delivered and acknowledged by the receiver, and all duplicate copies of the segments have "drained" from the internet ๐Ÿ’– Without such an assumption, two distinct TCP segments could conceivably be assigned the same or overlapping sequence numbers, causing confusion at the receiver as to which data is new and which is old. Remember that each segment is bound to as many consecutive sequence numbers as there are octets of data in the segment ๐Ÿ“

Under normal conditions, TCPs keep track of the next sequence number to emit and the oldest sequence number awaiting acknowledgment, so they don't accidentally reuse a sequence number before its first use has been acknowledged ๐ŸŒธ This alone does not guarantee that old duplicate data drains from the net, so the sequence space has been made very large to reduce the probability that a wandering duplicate causes trouble when it arrives. At 2 megabits/sec, it takes 4.5 hours to use up 2**32 octets of sequence space. Since the maximum segment lifetime in the net is not likely to exceed a few tens of seconds, this is deemed ample protection for foreseeable nets, even if data rates escalate to tens of megabits/sec. At 100 megabits/sec, the cycle time is 5.4 minutes, which may be a little short, but it's still within reason ๐Ÿ”ฅ

The basic duplicate detection and sequencing algorithm in TCP can be defeated, however, if a source TCP doesn't have any memory of the sequence numbers it last used on a given connection. For example, if the TCP were to start all connections with sequence number 0, then upon crashing and restarting, a TCP might re-form an earlier connection (possibly after half-open connection resolution) and emit packets with sequence numbers identical to or overlapping with packets still in the network, which were emitted on an earlier incarnation of the same connection ๐Ÿ˜ฑ In the absence of knowledge about the sequence numbers used on a particular connection, the TCP specification recommends that the source delay for MSL seconds before emitting segments on the connection, to allow time for segments from the earlier connection incarnation to drain from the system โญ

Even hosts that can remember the time of day and use it to select initial sequence number values are not immune from this problem (i.e., even if time of day is used to select an initial sequence number for each new connection incarnation) ๐Ÿ™ˆ

Suppose, for example, that a connection is opened starting with sequence number S. Suppose this connection isn't used much, and eventually the initial sequence number function (ISN(t)) takes on a value equal to the sequence number, say S1, of the last segment sent by this TCP on a particular connection. Now suppose that at this instant the host crashes, recovers, and establishes a new incarnation of the connection. The initial sequence number chosen is S1 = ISN(t), which is the last used sequence number on the old incarnation of the connection! ๐Ÿ’€ If the recovery happens quickly enough, any old duplicates in the net bearing sequence numbers in the neighborhood of S1 may arrive and be treated as new packets by the receiver of the new incarnation of the connection ๐Ÿ˜ญ

The problem is that the recovering host may not know how long it crashed, nor does it know whether there are still old duplicates in the system from earlier connection incarnations ๐Ÿฅบ

One way to deal with this problem is to deliberately delay emitting segments for one MSL after recovery from a crash. This is the "quiet time" specification. Hosts that prefer to avoid waiting, and are willing to risk possible confusion of old and new packets at a given destination, may choose not to wait for the "quiet time" ๐Ÿƒโ€โ™€๏ธ Implementors may provide TCP users with the ability to select, on a connection by connection basis, whether to wait after a crash, or may informally implement the "quiet time" for all connections. Obviously, even where a user selects to "wait," this is not necessary after the host has been "up" for at least MSL seconds ๐Ÿ‘‘

okay so to sum it all up ๐Ÿ’…: every segment that gets sent takes up one or more sequence numbers in the sequence space, and those numbers stay "busy" or "in use" until MSL seconds have passed. ๐Ÿ•ฐ๏ธ If a crash happens, there's a block of space-time that the octets of the last segment sent are sitting in. And if a new connection starts too soon and uses any of the sequence numbers in that footprint from the previous connection incarnation, there's a potential sequence number overlap that could confuse the receiver ๐Ÿ˜ญ๐Ÿซถ

3.4. Establishing a connection โœจ

The "three-way handshake" is the procedure used to establish a connection ๐Ÿค Usually one TCP starts it and another TCP responds. It also works if two TCPs start it at the same time ๐Ÿ‘ฏโ€โ™€๏ธ In that simultaneous case, each TCP gets a "SYN" segment with no acknowledgment after it has already sent its own "SYN". Of course, an old duplicate "SYN" segment showing up can make it look like a simultaneous connection initiation is happening ๐Ÿ™ˆ Using "reset" segments properly is how you tell these cases apart ๐Ÿ’…

Here are a few examples of connection initiation ๐Ÿฆ‹ These examples don't show connection synchronization with data-carrying segments, but that's perfectly legit, as long as the receiving TCP doesn't hand the data to the user until it's clear the data is valid. (So the data has to be buffered at the receiver until the connection reaches the ESTABLISHED state.) The three-way handshake cuts down on false connections ๐Ÿ›ก๏ธ It's a trade-off between memory and messages, since you need some info to do that checking โœจ

The simplest three-way handshake is shown in figure 7 below ๐ŸŽ€ Read the figures like this: each line is numbered so we can reference it. Right arrows (-->) mean a TCP segment is leaving TCP A for TCP B, or arriving at B from A. Left arrows (<--) mean the reverse. An ellipsis (...) means a segment is still in the network (delayed) ๐Ÿข An "XXX" means a segment got lost or rejected ๐Ÿ’€ Comments go in parentheses. TCP states show the state AFTER the segment departs or arrives (the segment's contents are in the middle of each line). The segment contents are abbreviated to sequence number, control flags, and ACK field. Other fields like window, addresses, lengths, and text are left out to keep things clear ๐Ÿงš

      TCP A                                                TCP B

  1.  CLOSED                                               LISTEN

  2.  SYN-SENT    --> <SEQ=100><CTL=SYN>               --> SYN-RECEIVED

  3.  ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK>  <-- SYN-RECEIVED

  4.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK>       --> ESTABLISHED

  5.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK><DATA> --> ESTABLISHED

          Basic 3-Way Handshake for Connection Synchronization

                                Figure 7.

In line 2 of figure 7, TCP A kicks things off by sending a SYN segment saying it'll use sequence numbers starting at 100 ๐ŸŒธ In line 3, TCP B sends its own SYN and acknowledges the SYN it got from TCP A. Notice the acknowledgment field says TCP B is now expecting to hear sequence 101, which acknowledges the SYN that used up sequence 100 ๐Ÿ˜คโœจ

At line 4, TCP A replies with an empty segment containing an ACK for TCP B's SYN. Then at line 5, TCP A finally sends some data ๐Ÿ’– The sequence number in line 5 is the same as in line 4, because the ACK doesn't take up any sequence number space. (If it did, we'd end up ACKing ACKs, and that's a whole mess ๐Ÿ˜ญ)

Simultaneous initiation is only a little more complicated, as figure 8 shows ๐Ÿ”ฅ Each TCP goes from CLOSED to SYN-SENT to SYN-RECEIVED to ESTABLISHED.

      TCP A                                            TCP B

  1.  CLOSED                                           CLOSED

  2.  SYN-SENT     --> <SEQ=100><CTL=SYN>              ...

  3.  SYN-RECEIVED <-- <SEQ=300><CTL=SYN>              <-- SYN-SENT

  4.               ... <SEQ=100><CTL=SYN>              --> SYN-RECEIVED

  5.  SYN-RECEIVED --> <SEQ=100><ACK=301><CTL=SYN,ACK> ...

  6.  ESTABLISHED  <-- <SEQ=300><ACK=101><CTL=SYN,ACK> <-- SYN-RECEIVED

  7.               ... <SEQ=101><ACK=301><CTL=ACK>     --> ESTABLISHED

                Simultaneous Connection Synchronization

                               Figure 8.

The main reason for the three-way handshake is to stop old duplicate connection initiations from causing chaos ๐ŸŒ€ To handle that, there's a special control message called reset ๐Ÿงน If the receiving TCP is in a non-synchronized state (SYN-SENT or SYN-RECEIVED), it goes back to LISTEN when it gets an acceptable reset. If the TCP is in one of the synchronized states (ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT), it aborts the connection and tells its user ๐Ÿ˜ณ We'll talk about that latter case under "half-open" connections below ๐Ÿ‘€

      TCP A                                                TCP B

  1.  CLOSED                                               LISTEN

  2.  SYN-SENT    --> <SEQ=100><CTL=SYN>               ...

  3.  (duplicate) ... <SEQ=90><CTL=SYN>               --> SYN-RECEIVED

  4.  SYN-SENT    <-- <SEQ=300><ACK=91><CTL=SYN,ACK>  <-- SYN-RECEIVED

  5.  SYN-SENT    --> <SEQ=91><CTL=RST>               --> LISTEN


  6.              ... <SEQ=100><CTL=SYN>               --> SYN-RECEIVED

  7.  SYN-SENT    <-- <SEQ=400><ACK=101><CTL=SYN,ACK>  <-- SYN-RECEIVED

  8.  ESTABLISHED --> <SEQ=101><ACK=401><CTL=ACK>      --> ESTABLISHED

                    Recovery from Old Duplicate SYN

                               Figure 9.

As a simple example of recovering from old duplicates, check out figure 9 ๐Ÿ•ต๏ธโ€โ™€๏ธ At line 3, an old duplicate SYN shows up at TCP B. TCP B can't tell it's old, so it responds normally (line 4). TCP A notices the ACK field is wrong and sends back a RST (reset), with its SEQ field picked so the segment looks believable ๐ŸŽญ When TCP B gets that RST, it goes back to LISTEN. Then the original SYN (pun intended) finally arrives at line 6, and the synchronization goes through normally โœจ If the SYN at line 6 had arrived before the RST, things would've gotten more complicated, with RSTs being sent in both directions ๐Ÿ™ƒ

Half-Open Connections and Other Anomalies

An established connection is "half-open" if one of the TCPs closed or aborted the connection on its end without the other one knowing, or if the two ends got desynchronized because a crash wiped out memory ๐Ÿฅบ These connections automatically get reset if someone tries to send data in either direction. That said, half-open connections are expected to be unusual, and the recovery procedure is kinda involved ๐Ÿซ 

If site A no longer has the connection, then when the user at site B tries to send data on it, the site B TCP gets a reset control message ๐Ÿšจ That message tells the site B TCP that something is wrong, and it's expected to abort the connection.

Okay, picture two user processes, A and B, communicating when a crash happens and A's TCP loses its memory ๐Ÿ’” Depending on the operating system running A's TCP, some error recovery mechanism might exist. When TCP is back up, A will probably start over from the beginning or from a recovery point. So A will likely try to OPEN the connection again, or try to SEND on the connection it still thinks is open. In the latter case, it gets the error message "connection not open" from its own local TCP ๐Ÿ™„ To establish the connection, A's TCP sends a segment containing SYN. This leads to the example in figure 10 ๐Ÿ‘‡ After TCP A crashes, the user tries to re-open the connection. Meanwhile, TCP B still thinks the connection is open ๐Ÿฅน

      TCP A                                           TCP B

  1.  (CRASH)                               (send 300,receive 100)

  2.  CLOSED                                           ESTABLISHED

  3.  SYN-SENT --> <SEQ=400><CTL=SYN>              --> (??)

  4.  (!!)     <-- <SEQ=300><ACK=100><CTL=ACK>     <-- ESTABLISHED

  5.  SYN-SENT --> <SEQ=100><CTL=RST>              --> (Abort!!)

  6.  SYN-SENT                                         CLOSED

  7.  SYN-SENT --> <SEQ=400><CTL=SYN>              -->

                     Half-Open Connection Discovery

                               Figure 10.

When the SYN arrives at line 3, TCP B is in a synchronized state and the incoming segment is outside the window, so it responds with an acknowledgment saying what sequence it expects next (ACK 100) ๐Ÿ™Œ TCP A sees that this segment doesn't acknowledge anything it sent. Since it's unsynchronized, it sends a reset (RST) because it's detected a half-open connection ๐Ÿ” TCP B aborts at line 5. TCP A keeps trying to establish the connection, and the problem is now just the basic 3-way handshake from figure 7 ๐Ÿ’…

Another interesting case happens when TCP A crashes and TCP B tries to send data on what it thinks is a synchronized connection ๐Ÿคฏ That's shown in figure 11. The data arriving at TCP A from TCP B (line 2) is unacceptable because no such connection exists, so TCP A sends a RST. The RST is acceptable, so TCP B processes it and aborts the connection ๐Ÿซฃ

        TCP A                                              TCP B

  1.  (CRASH)                                   (send 300,receive 100)

  2.  (??)    <-- <SEQ=300><ACK=100><DATA=10><CTL=ACK> <-- ESTABLISHED

  3.          --> <SEQ=100><CTL=RST>                   --> (ABORT!!)

           Active Side Causes Half-Open Connection Discovery

                               Figure 11.

In figure 12, TCP A and TCP B both have passive connections waiting for a SYN ๐Ÿงšโ€โ™€๏ธ An old duplicate arriving at TCP B (line 2) stirs B into action. A SYN-ACK goes back (line 3), and that makes TCP A generate a RST, since the ACK in line 3 isn't acceptable. TCP B accepts the reset and goes back to its passive LISTEN state ๐Ÿ’œ

      TCP A                                         TCP B

  1.  LISTEN                                        LISTEN

  2.       ... <SEQ=Z><CTL=SYN>                -->  SYN-RECEIVED

  3.  (??) <-- <SEQ=X><ACK=Z+1><CTL=SYN,ACK>   <--  SYN-RECEIVED

  4.       --> <SEQ=Z+1><CTL=RST>              -->  (return to LISTEN!)

  5.  LISTEN                                        LISTEN

       Old Duplicate SYN Initiates a Reset on two Passive Sockets

                               Figure 12.

A bunch of other cases are possible too, and they're all covered by the following rules for RST generation and processing ๐Ÿ“œ

Reset Generation

As a general rule, reset (RST) must be sent whenever a segment arrives that apparently isn't meant for the current connection ๐Ÿš€ A reset must not be sent if it isn't clear that this is the case ๐Ÿ™…โ€โ™€๏ธ

There are three groups of states:

  1. If the connection does not exist (CLOSED) then a reset is sent in response to any incoming segment except another reset. In particular, SYNs addressed to a non-existent connection are rejected by this means. ๐Ÿซถ

If the incoming segment has an ACK field, the reset takes its sequence number from that ACK field ๐Ÿ’… Otherwise the reset gets sequence number zero, and its ACK field is the sum of the incoming segment's sequence number and segment length ๐Ÿงฎ Either way, the connection stays in the CLOSED state ๐Ÿ”’

  1. If the connection is in any non-synchronized state (LISTEN, SYN-SENT, SYN-RECEIVED) and the incoming segment acknowledges something that hasn't been sent yet (the segment carries an unacceptable ACK), a reset is sent. The same goes if an incoming segment has a security level or compartment that doesn't exactly match the level and compartment requested for the connection ๐Ÿšซ

If our SYN hasn't been acknowledged and the precedence level of the incoming segment is higher than the one we requested, then either raise the local precedence level (if the user and the system allow it) or send a reset ๐Ÿ‘‘ If the incoming segment's precedence level is lower than the one we requested, keep going as if the precedence matched exactly. If the remote TCP can't raise its precedence level to match ours, that will show up in the next segment it sends, and the connection will be terminated then ๐Ÿซถ If our SYN has been acknowledged (maybe in this very incoming segment), the precedence level of the incoming segment has to match the local precedence level exactly. If it doesn't, a reset must be sent ๐Ÿ’€

If the incoming segment has an ACK field, the reset takes its sequence number from the ACK field of the segment. Otherwise, the reset has sequence number zero and the ACK field is set to the sum of the sequence number and segment length of the incoming segment. Either way, the connection remains in the same state ๐ŸŒˆ

  1. If the connection is in a synchronized state (ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT), any unacceptable segment (one with an out-of-window sequence number or an unacceptable acknowledgment number) must only get an empty acknowledgment segment back. That ACK carries the current send-sequence number and an acknowledgment of the next sequence number expected to be received. The connection stays in the same state ๐Ÿง

If an incoming segment has a security level, compartment, or precedence that doesn't exactly match the level, compartment, and precedence requested for the connection, a reset is sent and the connection goes to the CLOSED state. The reset takes its sequence number from the ACK field of the incoming segment ๐Ÿ™ˆ

Reset Processing ๐ŸŒธ

In all states except SYN-SENT, every reset (RST) segment gets validated by checking its SEQ fields. A reset is valid if its sequence number is in the window. In the SYN-SENT state (an RST received in response to an initial SYN), the RST is acceptable if its ACK field acknowledges the SYN ๐ŸŽ€

The receiver of an RST validates it first, then changes state. If the receiver was in the LISTEN state, it ignores the RST. If the receiver was in SYN-RECEIVED and had previously been in the LISTEN state, it goes back to LISTEN. Otherwise, the receiver aborts the connection and goes to CLOSED. If the receiver was in any other state, it aborts the connection, tells the user, and goes to CLOSED ๐Ÿ˜ญ

3.5. Closing a Connection ๐Ÿฆ‹

CLOSE means "I have no more data to send." Closing a full-duplex connection is kind of ambiguous, obviously, because it isn't clear how to treat the receiving side. We chose to treat CLOSE in a simplex fashion. The user who CLOSEs can keep RECEIVING until they're told the other side has CLOSED too. So a program could start several SENDs, then a CLOSE, then keep RECEIVING until it's signaled that a RECEIVE failed because the other side has CLOSED ๐Ÿ“

We assume the TCP will signal the user that the other side has closed, even if no RECEIVEs are outstanding, so the user can wrap up their side gracefully โœจ A TCP will reliably deliver every buffer SENT before the connection was CLOSED. So a user who doesn't expect any data back only needs to wait until they hear the connection was CLOSED successfully to know all their data reached the destination TCP ๐Ÿ’– Users must keep reading the connections they close for sending until the TCP says there's no more data ๐Ÿ“–

There are basically three cases:

  1. The user starts by telling the TCP to CLOSE the connection.
  2. The remote TCP starts by sending a FIN control signal.
  3. Both users CLOSE at the same time.

Case 1: Local user initiates the close ๐ŸŒท

In this case, a FIN segment can be built and placed on the outgoing segment queue. The TCP won't accept any more SENDs from the user, and it enters the FIN-WAIT-1 state. RECEIVEs are still allowed in this state. All segments up to and including the FIN get retransmitted until they're acknowledged. Once the other TCP has both acknowledged the FIN and sent a FIN of its own, the first TCP can ACK that FIN. Note that a TCP receiving a FIN will ACK it, but won't send its own FIN until its user has also CLOSED the connection ๐Ÿซง

Case 2: TCP receives a FIN from the network ๐Ÿงš

If an unsolicited FIN shows up from the network, the receiving TCP can ACK it and tell the user the connection is closing. The user responds with a CLOSE, and then the TCP can send a FIN to the other TCP after sending any remaining data. The TCP then waits until its own FIN is acknowledged, and then it deletes the connection. If no ACK shows up, the connection is aborted after the user timeout and the user is told ๐Ÿ˜ฌ

Case 3: Both users close simultaneously ๐Ÿ‘ฏ

A simultaneous CLOSE by the users at both ends causes FIN segments to be exchanged. Once all segments before the FINs have been processed and acknowledged, each TCP can ACK the FIN it received. When each one gets those ACKs, both will delete the connection ๐Ÿ”ฅ

      TCP A                                                TCP B

  1.  ESTABLISHED                                          ESTABLISHED

  2.  (Close)
      FIN-WAIT-1  --> <SEQ=100><ACK=300><CTL=FIN,ACK>  --> CLOSE-WAIT

  3.  FIN-WAIT-2  <-- <SEQ=300><ACK=101><CTL=ACK>      <-- CLOSE-WAIT

  4.                                                       (Close)
      TIME-WAIT   <-- <SEQ=300><ACK=101><CTL=FIN,ACK>  <-- LAST-ACK

  5.  TIME-WAIT   --> <SEQ=101><ACK=301><CTL=ACK>      --> CLOSED

  6.  (2 MSL)
      CLOSED

                         Normal Close Sequence

                               Figure 13.
      TCP A                                                TCP B

  1.  ESTABLISHED                                          ESTABLISHED

  2.  (Close)                                              (Close)
      FIN-WAIT-1  --> <SEQ=100><ACK=300><CTL=FIN,ACK>  ... FIN-WAIT-1
                  <-- <SEQ=300><ACK=100><CTL=FIN,ACK>  <--
                  ... <SEQ=100><ACK=300><CTL=FIN,ACK>  -->

  3.  CLOSING     --> <SEQ=101><ACK=301><CTL=ACK>      ... CLOSING
                  <-- <SEQ=301><ACK=101><CTL=ACK>      <--
                  ... <SEQ=101><ACK=301><CTL=ACK>      -->

  4.  TIME-WAIT                                            TIME-WAIT
      (2 MSL)                                              (2 MSL)
      CLOSED                                               CLOSED

                      Simultaneous Close Sequence

                               Figure 14.

3.6. Precedence and Security ๐Ÿ’œ

The idea is that a connection is only allowed between ports running with exactly the same security and compartment values, and at the higher of the precedence levels the two ports requested ๐Ÿ›ก๏ธ

The precedence and security parameters used in TCP are exactly the ones defined in the Internet Protocol (IP) [2]. Throughout this TCP specification, the term "security/compartment" means the security parameters used in IP, including security, compartment, user group, and handling restriction ๐Ÿง 

A connection attempt with mismatched security/compartment values, or a lower precedence value, must be rejected by sending a reset. A connection gets rejected for too low a precedence only after an acknowledgment of the SYN has been received ๐Ÿšซ

Heads up: TCP modules that only operate at the default precedence value still have to check the precedence of incoming segments, and they might need to raise the precedence level they use on the connection ๐Ÿ‘€

The security parameters may be used even in a non-secure environment (where the values would indicate unclassified data). So hosts in non-secure environments must be prepared to receive the security parameters, even though they don't need to send them ๐ŸŒธ

3.7. Data Communication โœจ

okay so once the connection is established, data gets moved around by swapping segments ๐Ÿ’Œ. Segments can get lost because of errors (the checksum test fails) or because the network is congested ๐Ÿ˜ญ, so TCP uses retransmission after a timeout to make sure every single segment arrives. Duplicate segments can also show up, thanks to the network or TCP's own retransmissions. Like we talked about in the sequence numbers section, TCP runs certain tests on the sequence and acknowledgment numbers in each segment to check that they're acceptable ๐Ÿ”.

The sender keeps track of the next sequence number to use in SND.NXT. The receiver keeps track of the next sequence number it expects in RCV.NXT. The sender also tracks the oldest unacknowledged sequence number in SND.UNA. If the data flow is momentarily idle and everything sent has been acknowledged, all three variables are equal ๐Ÿซถ.

When the sender builds a segment and transmits it, the sender advances SND.NXT. When the receiver accepts a segment, it advances RCV.NXT and sends an acknowledgment. When the data sender gets an acknowledgment, it advances SND.UNA. How far apart these values are is a measure of the delay in the communication ๐Ÿข. The amount each variable moves is the length of the data in the segment. Also, once you're in the ESTABLISHED state, every segment must carry current acknowledgment information, no exceptions ๐Ÿ’….

The CLOSE user call implies a push function, and so does the FIN control flag in an incoming segment ๐ŸŽ€.

Retransmission Timeout

literally the network is so unpredictable (it's an internetwork, it's a whole mess ๐ŸŒ), and TCP connections get used for so many different things, so the retransmission timeout has to be figured out dynamically ๐Ÿง . The spec gives one procedure as an example, just to show how it could work.

An Example Retransmission Timeout Procedure

Here's the vibe. You measure the time between sending a data octet with a particular sequence number and receiving an acknowledgment that covers that sequence number. (The segments you send don't have to match the segments you receive.) That measured time is the Round Trip Time (RTT) โฑ๏ธ. Next you compute a Smoothed Round Trip Time (SRTT) like this:

SRTT = ( ALPHA * SRTT ) + ((1-ALPHA) * RTT)

Then, based on that, you compute the retransmission timeout (RTO):

RTO = min[UBOUND,max[LBOUND,(BETA*SRTT)]]

where UBOUND is an upper bound on the timeout (e.g., 1 minute), LBOUND is a lower bound on the timeout (e.g., 1 second), ALPHA is a smoothing factor (e.g., .8 to .9), and BETA is a delay variance factor (e.g., 1.3 to 2.0) ๐Ÿฆ‹.

The Communication of Urgent Information

The whole point of the TCP urgent mechanism is to let the sending user poke the receiving user into accepting some urgent data ๐Ÿšจ. It also lets the receiving TCP tell its user when all the urgent data it currently knows about has been received ๐Ÿ’–.

This mechanism lets a point in the data stream be marked as the end of the urgent information. Whenever that point is ahead of the receive sequence number (RCV.NXT) at the receiving TCP, that TCP must tell the user to go into "urgent mode". When the receive sequence number catches up to the urgent pointer, the TCP must tell the user to go into "normal mode" ๐Ÿ”. If the urgent pointer gets updated while the user is in "urgent mode", the user won't see the update at all ๐Ÿ™ˆ.

The method uses an urgent field that's carried in every segment that gets transmitted. The URG control flag says the urgent field is meaningful, and that its value has to be added to the segment sequence number to get the urgent pointer. If the flag isn't there, there's no urgent data outstanding ๐ŸŒธ.

To send an urgent indication, the user also must send at least one data octet โœ๏ธ. If the sending user also indicates a push, the urgent information gets to the destination process faster โšก.

Managing the Window

The window in each segment tells you the range of sequence numbers that the sender of the window (the data receiver) is ready to accept right now ๐ŸชŸ. The assumption is that this is tied to how much data buffer space is available for the connection.

A big window encourages transmissions. If more data shows up than can be accepted, it gets thrown away ๐Ÿ—‘๏ธ, which causes a ton of retransmissions, adding pointless load to the network and the TCPs ๐Ÿ˜ฉ. A small window can choke off data so badly that you end up with a round trip delay between every new segment ๐ŸŒ.

The mechanisms let a TCP advertise a large window and then later advertise a much smaller one, without having accepted that much data. This is called "shrinking the window," and it is strongly discouraged ๐Ÿ™…โ€โ™€๏ธ. The robustness principle says TCPs will not shrink the window themselves, but they will be ready for other TCPs to do it ๐Ÿซถ.

The sending TCP must be ready to accept new data from the user and send at least one octet of it, even when the send window is zero. The sending TCP must also keep retransmitting to the receiving TCP regularly, even when the window is zero. Two minutes is recommended for the retransmission interval while the window is zero โฐ. This retransmission is essential, because it guarantees that when either TCP has a zero window, the window reopening gets reliably reported to the other side ๐Ÿ’Œ.

When the receiving TCP has a zero window and a segment arrives, it must still send an acknowledgment showing its next expected sequence number and its current window, which is zero 0๏ธโƒฃ.

The sending TCP packages the data it's sending into segments that fit the current window, and it may repackage the segments on the retransmission queue. Repackaging is not required, but it may be helpful ๐Ÿ“ฆ.

In a connection with one-way data flow, the window information rides in acknowledgment segments that all share the same sequence number. That means there's no way to reorder them if they arrive out of order ๐Ÿ˜ตโ€๐Ÿ’ซ. It's not a huge deal, but it means the window info can occasionally be based on old reports from the data receiver. The fix is to act on window information only from segments that carry the highest acknowledgment number, meaning segments whose acknowledgment number is equal to or greater than the highest one received before ๐Ÿ†.

Window management has a big impact on performance, so here are some suggestions for implementers ๐Ÿ“.

Window Management Suggestions

Allocating a very small window makes data get sent in lots of tiny segments, when fewer big segments would actually perform better ๐Ÿœ.

One way to dodge small windows is for the receiver to hold off on updating a window until the new allocation is at least X percent of the maximum allocation possible for the connection (where X might be 20 to 40) ๐Ÿง˜.

Another idea is for the sender to avoid sending small segments by waiting until the window is big enough before sending data. If the user signals a push function, though, the data must be sent even if it's a small segment ๐Ÿš€.

Heads up that acknowledgments should not be delayed, or you'll get unnecessary retransmissions ๐Ÿ™…. One strategy is to send an acknowledgment as soon as a small segment arrives (without updating the window information), and then send another acknowledgment with the new window information once the window is larger ๐Ÿ’ก.

The segment that probes a zero window can also kick off a slide into smaller and smaller segments ๐Ÿ“‰. If a segment with a single data octet, sent to probe a zero window, gets accepted, it uses up one octet of the window that just opened. If the sending TCP just sends as much as it can whenever the window is non-zero, the data ends up split into alternating big and small segments ๐ŸŽข. Over time, occasional pauses where the receiver frees up window space break the big segments into a small and a not-quite-so-big pair. After a while, the transmission is mostly small segments ๐Ÿฅฒ.

The takeaway is that TCP implementations need to actively try to combine small window allocations into larger windows ๐Ÿงฉ, since the window management mechanisms tend to create lots of small windows in the simplest implementations.


3.8. Interfaces

There are, of course, two interfaces to care about: the user/TCP interface and the TCP/lower-level interface ๐Ÿ”Œ. We have a pretty detailed model of the user/TCP interface, but the interface to the lower level protocol module is left unspecified here, since the lower level protocol's own specification will cover it in detail. For the case where the lower level is IP, we do note some of the parameter values TCPs might use ๐ŸŒˆ.

User/TCP Interface

The functional description of user commands to TCP below is, at best, fictional ๐Ÿงš, because every operating system has different facilities. So readers should be warned that different TCP implementations may have different user interfaces. Even so, all TCPs must provide a certain minimum set of services, so that every TCP implementation can support the same protocol hierarchy ๐Ÿ—๏ธ. This section specifies the functional interfaces that are required of all TCP implementations ๐Ÿ’œ.

TCP User Commands

The following sections functionally describe a USER/TCP interface. The notation looks like most procedure or function calls in high-level languages, but that doesn't rule out trap-type service calls (e.g., SVCs, UUOs, EMTs) ๐Ÿงพ.

The user commands below specify the basic functions the TCP must perform to support interprocess communication. Each implementation has to define its own exact format, and it may offer combinations or subsets of the basic functions in single calls. In particular, some implementations may want to automatically OPEN a connection on the first SEND or RECEIVE the user issues for a given connection ๐ŸŽฏ.

When it's providing interprocess communication, the TCP must not only accept commands, but also return information to the processes it serves. That information consists of:

  • (a) general information about a connection (e.g., interrupts, remote close, binding of unspecified foreign socket).
  • (b) replies to specific user commands indicating success or various types of failure.

Open

Format:

OPEN (local port, foreign socket, active/passive
[, timeout] [, precedence] [, security/compartment] [, options])
-> local connection name

We assume the local TCP knows the identity of the processes it serves, and it will check that the process is authorized to use the connection specified ๐Ÿ”. Depending on the TCP implementation, the local network and TCP identifiers for the source address will be supplied either by the TCP or by the lower level protocol (e.g., IP) ๐Ÿชช. These considerations come from concern about security, to the extent that no TCP should be able to masquerade as another one, and so on ๐Ÿ•ต๏ธโ€โ™€๏ธ. Similarly, no process can masquerade as another without the collusion of the TCP ๐Ÿซฃ.

If the active/passive flag is set to passive, then this is a call to LISTEN for an incoming connection ๐Ÿ‘‚โœจ. A passive open MAY have either a fully specified foreign socket, so it waits for one particular connection, or an unspecified foreign socket, so it waits for any call at all ๐Ÿฆ‹. A fully specified passive call can be turned active later by running a SEND ๐Ÿ’….

A transmission control block (TCB) gets created and partly filled in with the data from the OPEN command parameters ๐Ÿ“.

On an active OPEN command, TCP starts the procedure to synchronize (aka establish) the connection right away ๐Ÿš€.

The timeout, if there is one, lets the caller set a timeout for all the data submitted to TCP โฐ. If the data isn't delivered to the destination within that timeout period, TCP aborts the connection ๐Ÿ’€. The present global default is five minutes ๐Ÿ•”.

TCP, or some part of the operating system, checks that the user is allowed to open a connection with the specified precedence or security/compartment ๐Ÿ”. If the OPEN call doesn't specify precedence or security/compartment, the default values MUST be used ๐ŸŽ€.

TCP only accepts incoming requests as a match if the security/compartment information is exactly the same, AND the precedence is equal to or higher than the precedence requested in the OPEN call ๐Ÿ™Œ.

The precedence for the connection is the higher of the values requested in the OPEN call and received from the incoming request, and it stays fixed at that value for the life of the connection ๐Ÿ‘‘. Implementers MAY want to give the user control over this precedence negotiation ๐ŸŽ›๏ธ. For example, the user might be allowed to specify that precedence must be matched exactly, or that any attempt to raise it gets confirmed by the user first ๐Ÿ™ˆ.

TCP gives the user a local connection name ๐Ÿท๏ธ. That name can then be used as a shorthand for the connection defined by the <local socket, foreign socket> pair ๐Ÿซถ.


Send ๐Ÿ’Œ

Format:

SEND (local connection name, buffer address, byte
count, PUSH flag, URGENT flag [,timeout])

This call sends the data in the indicated user buffer over the indicated connection ๐Ÿ“จ. If the connection hasn't been opened, the SEND counts as an error ๐Ÿ˜ฌ. Some implementations MAY let users SEND first, and then an automatic OPEN happens ๐Ÿช„. If the calling process isn't authorized to use this connection, an error comes back ๐Ÿšซ.

If the PUSH flag is set, the data MUST be transmitted promptly to the receiver, and the PUSH bit gets set in the last TCP segment made from the buffer ๐Ÿƒโ€โ™€๏ธ๐Ÿ’จ. If the PUSH flag is not set, the data MAY be combined with data from later SENDs so transmission is more efficient โšก.

If the URGENT flag is set, the segments sent to the destination TCP will have the urgent pointer set ๐Ÿšจ. The receiving TCP signals the urgent condition to the receiving process if the urgent pointer shows that data before it hasn't been consumed yet ๐Ÿ“ฃ. The whole point of urgent is to hype the receiver up to process the urgent data, and to tell the receiver when all the currently known urgent data has arrived ๐Ÿ“ข. The number of times the sending user's TCP signals urgent won't necessarily match the number of times the receiving user gets told about urgent data ๐Ÿคทโ€โ™€๏ธ.

If no foreign socket was specified in the OPEN, but the connection is established anyway (for example, because a LISTENing connection got specific after a foreign segment arrived for the local socket), then the designated buffer is sent to the implied foreign socket ๐ŸŽฏ. People who use OPEN with an unspecified foreign socket can still use SEND without ever explicitly knowing the foreign socket address ๐Ÿง .

BUT, if a SEND is tried before the foreign socket gets specified, an error is returned ๐Ÿ™…โ€โ™€๏ธ. Users can use the STATUS call to check the status of the connection ๐Ÿ”. In some implementations, TCP MAY tell the user when an unspecified socket gets bound ๐Ÿ””.

If a timeout is specified, the current user timeout for this connection changes to the new one โฑ๏ธ.

In the simplest implementation, SEND wouldn't return control to the sending process until either the transmission was complete or the timeout was exceeded ๐Ÿ˜ด. But that simple method can deadlock (for example, both sides might try to do SENDs before doing any RECEIVEs) AND it performs poorly, so it is NOT RECOMMENDED ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’”. A more sophisticated implementation returns immediately, so the process can run at the same time as network I/O, and it also lets multiple SENDs be in progress at once ๐ŸŽ๏ธ. Multiple SENDs get served first come, first served, so TCP queues the ones it can't service right away ๐Ÿงพ.

We've been assuming an asynchronous user interface, where a SEND later gets some kind of SIGNAL or pseudo-interrupt from the serving TCP ๐Ÿ“ฌ. The other option is to return a response right away ๐Ÿƒ. For instance, SENDs might return an immediate local acknowledgment, even if the distant TCP hasn't acknowledged the segment yet ๐Ÿคž. We could optimistically assume eventual success, and if we're wrong, the connection closes anyway due to the timeout โŒ›. In implementations like that (synchronous), there are still some asynchronous signals, but they deal with the connection itself, not with specific segments or buffers ๐Ÿงฉ.

So the process can tell apart the error and success indications for different SENDs, it might be appropriate for the buffer address to come back along with the coded response to the SEND request ๐Ÿ—‚๏ธ. TCP-to-user signals get discussed below, and they show what information SHOULD be returned to the calling process ๐Ÿ“‹.


Receive ๐Ÿ“ฅ

Format:

RECEIVE (local connection name, buffer address, byte
count) -> byte count, urgent flag, push flag

This command allocates a receiving buffer for the specified connection ๐Ÿ›๏ธ. If no OPEN came before it, or the calling process isn't authorized to use this connection, an error is returned ๐Ÿ™…โ€โ™€๏ธ.

In the simplest implementation, control wouldn't go back to the calling program until either the buffer was full or some error happened, but this scheme is super prone to deadlocks ๐Ÿ˜ตโ€๐Ÿ’ซ. A more sophisticated implementation lets several RECEIVEs be outstanding at once ๐ŸŽช. They get filled as segments arrive ๐Ÿ“ฆ. This strategy gives more throughput, but the cost is a fancier (possibly asynchronous) scheme to tell the calling program that a PUSH was seen or a buffer got filled ๐Ÿ””.

If enough data arrives to fill the buffer before a PUSH is seen, the PUSH flag won't be set in the response to the RECEIVE ๐Ÿซ™. The buffer gets filled with as much data as it can hold ๐Ÿ’ฏ. If a PUSH is seen before the buffer is full, the buffer comes back partially filled with PUSH indicated ๐Ÿซธ.

If there's urgent data, the user was informed as soon as it arrived, through a TCP-to-user signal ๐Ÿšจ. The receiving user SHOULD therefore be in "urgent mode" ๐Ÿซจ. If the URGENT flag is on, more urgent data is still on the way ๐Ÿ›ฃ๏ธ. If the URGENT flag is off, this RECEIVE call has returned all the urgent data, and the user MAY now leave "urgent mode" ๐Ÿฅณ. Heads up: data after the urgent pointer (non-urgent data) can't be delivered to the user in the same buffer as preceding urgent data, unless the boundary is clearly marked for the user ๐Ÿšง.

To tell apart several outstanding RECEIVEs, and to handle the case where a buffer isn't completely filled, the return code comes with both a buffer pointer and a byte count showing the actual length of the data received ๐Ÿ”ข.

Other ways to do RECEIVE could have TCP allocate the buffer storage, or TCP could share a ring buffer with the user ๐Ÿ’.


Close ๐Ÿšช

Format:

CLOSE (local connection name)

This command closes the specified connection ๐Ÿ”’. If the connection isn't open, or the calling process isn't authorized to use this connection, an error is returned โŒ. Closing is meant to be graceful ๐Ÿซง: outstanding SENDs keep getting transmitted (and retransmitted) as flow control allows, until they've all been serviced ๐ŸŒท. So it should be fine to make several SEND calls, then a CLOSE, and expect all the data to reach the destination ๐Ÿ’…. Users SHOULD also keep RECEIVEing on CLOSING connections, because the other side might still be sending the last of its data ๐Ÿ“ญ. So CLOSE means "I have no more to send," but it does NOT mean "I will not receive any more" ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’–. It can happen (if the user-level protocol isn't well thought out) that the closing side can't get rid of all its data before timing out ๐Ÿ˜ฉ. When that happens, CLOSE turns into ABORT, and the closing TCP gives up ๐Ÿณ๏ธ.

The user MAY CLOSE the connection at any time on their own initiative, or in response to various prompts from TCP (for example, a remote close was executed, the transmission timeout was exceeded, or the destination is inaccessible) ๐ŸŽฌ.

Closing needs to talk to the foreign TCP, so connections MAY remain in the closing state for a short time โณ. Trying to reopen the connection before TCP replies to the CLOSE command will get you error responses ๐Ÿšซ.

Close also implies the push function ๐Ÿซธ.


Status ๐Ÿ”

Format:

STATUS (local connection name) -> status data

This is an implementation-dependent user command, and it could be left out without any bad effects ๐Ÿคทโ€โ™€๏ธ. The information returned would typically come from the TCB tied to the connection ๐Ÿ—ƒ๏ธ.

This command returns a data block with the following info ๐Ÿ“‹:

local socket,
foreign socket,
local connection name,
receive window,
send window,
connection state,
number of buffers awaiting acknowledgment,
number of buffers pending receipt,
urgent state,
precedence,
security/compartment,
and transmission timeout.

Depending on the state of the connection, or on the implementation itself, some of this info may not be available or meaningful ๐Ÿ™ƒ. If the calling process isn't authorized to use this connection, an error is returned ๐Ÿ›‘. That's the point: it stops unauthorized processes from snooping on a connection ๐Ÿ•ต๏ธโ€โ™€๏ธ๐Ÿ”.


Abort ๐Ÿ›‘

Format:

ABORT (local connection name)

3.8. Interfaces (continued) ๐Ÿ’…

Okay so ABORT is basically the dramatic exit ๐Ÿ’€. It causes all pending SENDs and RECEIVES to get aborted ๐Ÿ™…โ€โ™€๏ธ, the TCB gets removed ๐Ÿ—‘๏ธ, and a special RESET message gets sent to the TCP on the other side of the connection ๐Ÿš€. Depending on the implementation, users might get an abort indication for each outstanding SEND or RECEIVE, or they might just get an ABORT-acknowledgment. Either way it's giving main character exit ๐ŸŽ€

TCP-to-User Messages

Okay so the operating system is assumed to give the TCP a way to asynchronously tap the user program on the shoulder ๐Ÿ‘€. When the TCP does signal a user program, certain info gets passed along. Often that info is an error message ๐Ÿ˜ญ. Other times it's info about finishing a SEND or RECEIVE or some other user call โœจ. Here's what gets passed along:

        Local Connection Name                    Always
        Response String                          Always
        Buffer Address                           Send & Receive
        Byte count (counts bytes received)       Receive
        Push flag                                Receive
        Urgent flag                              Receive

TCP/Lower-Level Interface

The TCP calls on a lower level protocol module to actually send and receive info over a network ๐ŸŒ. One case is the ARPA internetwork system, where the lower level module is the Internet Protocol (IP) [2] ๐Ÿฆ‹.

If the lower level protocol is IP, it provides arguments for a type of service and for a time to live. TCP uses these settings for those parameters ๐Ÿงš:

      Type of Service = Precedence: routine, Delay: normal, Throughput:
      normal, Reliability: normal; or 00000000.

      Time to Live    = one minute, or 00111100.
Note that the assumed maximum segment lifetime is two minutes ๐Ÿ‘€. Here we explicitly ask that a segment be destroyed if it cannot be delivered by the internet system within one minute. That's a very firm boundary, bestie ๐Ÿ™…โ€โ™€๏ธ.

If the lower level is IP (or another protocol that provides this feature) and source routing is used, the interface must allow the route information to be communicated ๐Ÿ—บ๏ธ. This is especially important so that the source and destination addresses used in the TCP checksum are the originating source and ultimate destination ๐Ÿ’–. It's also important to preserve the return route so connection requests can be answered ๐Ÿซถ.

Any lower level protocol will have to provide the source address, destination address, and protocol fields, plus some way to determine the "TCP length". It has to do this both to provide the functional equivlent service of IP and to be used in the TCP checksum ๐ŸŒธ.

3.9. Event Processing โœจ

The processing in this section is an example of one possible implementation ๐Ÿ”ฅ. Other implementations may have slightly different processing sequences, but they should differ from those in this section only in detail, not in substance ๐Ÿ’œ.

The TCP is basically a responder, bestie ๐Ÿงš. It reacts to events, and the events fall into three categories: user calls, arriving segments, and timeouts. This section describes what the TCP does for each event ๐Ÿ’…. A lot of the time, the processing depends on the state of the connection ๐Ÿ‘‘.

Here are the events that can happen:

      User Calls

        OPEN
        SEND
        RECEIVE
        CLOSE
        ABORT
        STATUS

      Arriving Segments

        SEGMENT ARRIVES

      Timeouts

        USER TIMEOUT
        RETRANSMISSION TIMEOUT
        TIME-WAIT TIMEOUT

The model for the TCP/user interface is that user commands get an immediate return, and possibly a delayed response via an event or pseudo interrupt โญ. In the descriptions below, the term "signal" means cause a delayed response ๐Ÿฆ‹.

Error responses are given as character strings ๐ŸŽ€. For example, user commands that reference connections that don't exist get "error: connection not open" ๐Ÿ™ˆ.

Please note that all arithmetic on sequence numbers, acknowledgment numbers, windows, et cetera, is modulo 2**32, the size of the sequence number space ๐Ÿ”ข. Also note that "=<" means less than or equal to (modulo 2**32) ๐Ÿ’–.

A natural way to think about processing incoming segments is to imagine they're first tested for proper sequence number. That means checking that their contents lie in the range of the expected "receive window" in the sequence number space ๐Ÿ‘€. Then they're generally queued and processed in sequence number order ๐Ÿซถ.

When a segment overlaps other already received segments, we reconstruct the segment to contain just the new data, and adjust the header fields so everything stays consistent ๐ŸŒˆ.

Note that if no state change is mentioned, the TCP stays in the same state ๐ŸŒธ.

OPEN Call

CLOSED STATE (i.e., TCB does not exist)

Create a new transmission control block (TCB) to hold connection state info ๐ŸŽ€. Fill in the local socket identifier, foreign socket, precedence, security/compartment, and user timeout info. Note that some parts of the foreign socket may be unspecified in a passive OPEN, and they're filled in by the parameters of the incoming SYN segment ๐Ÿงš. Verify that the security and precedence requested are allowed for this user. If they aren't, return "error: precedence not allowed" or "error: security/compartment not allowed." ๐Ÿ™…โ€โ™€๏ธ If passive, enter the LISTEN state and return. If active and the foreign socket is unspecified, return "error: foreign socket unspecified". If active and the foreign socket is specified, issue a SYN segment ๐Ÿš€. An initial send sequence number (ISS) is selected. A SYN segment of the form <SEQ=ISS><CTL=SYN> is sent. Set SND.UNA to ISS, SND.NXT to ISS+1, enter SYN-SENT state, and return ๐Ÿ’–.

If the caller doesn't have access to the local socket specified, return "error: connection illegal for this process" ๐Ÿ˜ญ. If there's no room to create a new connection, return "error: insufficient resources" ๐Ÿ’€.

LISTEN STATE

If active and the foreign socket is specified, then change the connection from passive to active, and select an ISS ๐Ÿฆ‹. Send a SYN segment, set SND.UNA to ISS, and SND.NXT to ISS+1. Enter SYN-SENT state. Data associated with SEND may be sent with the SYN segment or queued for transmission after entering ESTABLISHED state โœจ. The urgent bit, if requested in the command, must be sent with the data segments sent as a result of this command ๐Ÿ”ฅ. If there's no room to queue the request, respond with "error: insufficient resources". If the foreign socket wasn't specified, then return "error: foreign socket unspecified" ๐Ÿ™ˆ.

SYN-SENT STATE, SYN-RECEIVED STATE, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE

Return "error: connection already exists" ๐Ÿ’….

SEND Call

CLOSED STATE (i.e., TCB does not exist)

If the user doesn't have access to such a connection, then return "error: connection illegal for this process" ๐Ÿ™…โ€โ™€๏ธ.

Otherwise, return "error: connection does not exist" ๐Ÿ˜ญ.

LISTEN STATE

If the foreign socket is specified, then change the connection from passive to active, and select an ISS ๐Ÿš€. Send a SYN segment, set SND.UNA to ISS, and SND.NXT to ISS+1. Enter SYN-SENT state. Data associated with SEND may be sent with the SYN segment or queued for transmission after entering ESTABLISHED state ๐ŸŒธ. The urgent bit, if requested in the command, must be sent with the data segments sent as a result of this command ๐Ÿซถ. If there's no room to queue the request, respond with "error: insufficient resources". If the foreign socket wasn't specified, then return "error: foreign socket unspecified" ๐Ÿ‘‘.

SYN-SENT STATE, SYN-RECEIVED STATE

Queue the data for transmission after entering ESTABLISHED state ๐Ÿงš. If there's no space to queue, respond with "error: insufficient resources" ๐Ÿ’€.

ESTABLISHED STATE, CLOSE-WAIT STATE

Segmentize the buffer and send it with a piggybacked acknowledgment (acknowledgment value = RCV.NXT) ๐Ÿฆ‹. If there's insufficient space to remember this buffer, simply return "error: insufficient resources" ๐Ÿ˜ญ.

If the urgent flag is set, then SND.UP <- SND.NXT-1 and set the urgent pointer in the outgoing segments ๐Ÿ”ฅ.

FIN-WAIT-1 STATE, FIN-WAIT-2 STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE

Return "error: connection closing" and do not service the request ๐Ÿ™…โ€โ™€๏ธ.

RECEIVE Call

CLOSED STATE (i.e., TCB does not exist)

If the user doesn't have access to such a connection, return "error: connection illegal for this process" ๐Ÿ™ˆ.

Otherwise, return "error: connection does not exist" ๐Ÿ’….

LISTEN STATE, SYN-SENT STATE, SYN-RECEIVED STATE

Queue it for processing after entering ESTABLISHED state โœจ. If there's no room to queue this request, respond with "error: insufficient resources" ๐Ÿ’€.

ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE

If insufficient incoming segments are queued to satisfy the request, queue the request ๐ŸŒˆ. If there's no queue space to remember the RECEIVE, respond with "error: insufficient resources" ๐Ÿ˜ญ.

Reassemble the queued incoming segments into the receive buffer and return to the user. Mark "push seen" (PUSH) if this is the case ๐ŸŽ€.

If RCV.UP is ahead of the data currently being passed to the user, notify the user of the presence of urgent data ๐Ÿ‘€.

When the TCP takes responsibility for delivering data to the user, that fact must be communicated to the sender via an acknowledgment ๐Ÿซถ. The formation of such an acknowledgment is described below, in the discussion of processing an incoming segment ๐Ÿฆ‹.

CLOSE-WAIT STATE

Since the remote side has already sent a FIN, RECEIVEs must be satisfied by text that's already on hand but not yet delivered to the user ๐Ÿงš. If no text is waiting to be delivered, the RECEIVE will get an "error: connection closing" response ๐Ÿ˜ญ. Otherwise, any remaining text can be used to satisfy the RECEIVE ๐ŸŒธ.

CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE

Return "error: connection closing" ๐Ÿ™…โ€โ™€๏ธ.

CLOSE Call

CLOSED STATE (i.e., TCB does not exist)

If the user doesn't have access to such a connection, return "error: connection illegal for this process" ๐Ÿ™ˆ.

Otherwise, return "error: connection does not exist" ๐Ÿ’€.

LISTEN STATE

Any outstanding RECEIVEs are returned with "error: closing" responses ๐Ÿ”ฅ. Delete the TCB, enter CLOSED state, and return ๐Ÿฆ‹.

SYN-SENT STATE

Delete the TCB and return "error: closing" responses to any queued SENDs or RECEIVEs ๐Ÿ˜ญ.

SYN-RECEIVED STATE

If no SENDs have been issued and there's no pending data to send, then form a FIN segment, send it, and enter FIN-WAIT-1 state ๐Ÿš€. Otherwise, queue it for processing after entering ESTABLISHED state ๐Ÿซถ.

ESTABLISHED STATE

Queue this until all preceding SENDs have been segmentized, then form a FIN segment and send it โœจ. In any case, enter FIN-WAIT-1 state ๐Ÿ’….

FIN-WAIT-1 STATE, FIN-WAIT-2 STATE

Strictly speaking, this is an error and should receive an "error: connection closing" response ๐Ÿ™ˆ. An "ok" response would be acceptable too, as long as a second FIN isn't emitted (the first FIN may be retransmitted, though) ๐ŸŒˆ.

CLOSE-WAIT STATE

Queue this request until all preceding SENDs have been segmentized. Then send a FIN segment and enter CLOSING state ๐Ÿ‘‘.

CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE

Respond with "error: connection closing" ๐ŸŽ€.

ABORT Call

CLOSED STATE (i.e., TCB does not exist) is where the connection doesn't even exist yet, so the answer depends on who's asking ๐Ÿ‘€

  • If the user should not have access to such a connection, return "error: connection illegal for this process" ๐Ÿšซ
  • Otherwise return "error: connection does not exist" ๐Ÿซ 

LISTEN STATE ๐ŸŽง

  • Any outstanding RECEIVEs should be returned with "error: connection reset" responses. Delete the TCB, enter CLOSED state, and return. Bye bye, listener ๐Ÿ‘‹

SYN-SENT STATE ๐Ÿค

  • All queued SENDs and RECEIVEs should be given "connection reset" notification, the TCB gets deleted, enter CLOSED state, and return. The handshake got ghosted ๐Ÿ’€

SYN-RECEIVED STATE, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE, and CLOSE-WAIT STATE ๐Ÿ’…

  • Send a reset segment:
<SEQ=SND.NXT><CTL=RST>
  • All queued SENDs and RECEIVEs should be given "connection reset" notification. All segments queued for transmission (except for the RST formed above) or retransmission should be flushed, the TCB gets deleted, enter CLOSED state, and return. Everything gets cleaned up, periodt โœจ

CLOSING STATE, LAST-ACK STATE, and TIME-WAIT STATE ๐Ÿฆ‹

  • Respond with "ok", delete the TCB, enter CLOSED state, and return. Calm exit, very iconic ๐ŸŒธ

STATUS Call ๐Ÿ“Š

CLOSED STATE (i.e., TCB does not exist) ๐ŸŒ™

  • If the user should not have access to such a connection, return "error: connection illegal for this process" ๐Ÿšซ
  • Otherwise return "error: connection does not exist" ๐Ÿซ 

LISTEN STATE ๐ŸŽง

  • Return "state = LISTEN", and the TCB pointer.

SYN-SENT STATE ๐Ÿค

  • Return "state = SYN-SENT", and the TCB pointer.

SYN-RECEIVED STATE ๐Ÿ“ฅ

  • Return "state = SYN-RECEIVED", and the TCB pointer.

ESTABLISHED STATE ๐Ÿ’–

  • Return "state = ESTABLISHED", and the TCB pointer. The connection is thriving ๐ŸŒˆ

FIN-WAIT-1 STATE ๐Ÿ‘‹

  • Return "state = FIN-WAIT-1", and the TCB pointer.

FIN-WAIT-2 STATE ๐Ÿ‘‹

  • Return "state = FIN-WAIT-2", and the TCB pointer.

CLOSE-WAIT STATE ๐Ÿšช

  • Return "state = CLOSE-WAIT", and the TCB pointer.

CLOSING STATE ๐Ÿซ‚

  • Return "state = CLOSING", and the TCB pointer.

LAST-ACK STATE ๐Ÿฅ€

  • Return "state = LAST-ACK", and the TCB pointer.

TIME-WAIT STATE โณ

  • Return "state = TIME-WAIT", and the TCB pointer.

SEGMENT ARRIVES ๐Ÿš€

Okay so this is where incoming segments get sorted out, and it's a whole thing ๐Ÿงš

If the state is CLOSED (i.e., TCB does not exist) then ๐ŸŒ‘

  • All data in the incoming segment is discarded. An incoming segment containing a RST is discarded. An incoming segment not containing a RST causes a RST to be sent in response. The acknowledgment and sequence field values are selected to make the reset sequence acceptable to the TCP that sent the offending segment ๐Ÿ™ˆ
  • If the ACK bit is off, sequence number zero is used:
<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
  • If the ACK bit is on:
<SEQ=SEG.ACK><CTL=RST>
  • Return.

If the state is LISTEN then ๐ŸŽง

  • First, check for an RST. An incoming RST should be ignored. Return. Not your drama, not your problem ๐Ÿซถ
  • Second, check for an ACK. Any acknowledgment is bad if it arrives on a connection still in the LISTEN state. An acceptable reset segment should be formed for any arriving ACK-bearing segment. The RST should be formatted as follows:
<SEQ=SEG.ACK><CTL=RST>
  • Return.
  • Third, check for a SYN. If the SYN bit is set, check the security. If the security/compartment on the incoming segment does not exactly match the security/compartment in the TCB, then send a reset and return:
<SEQ=SEG.ACK><CTL=RST>
  • If the SEG.PRC is greater than the TCB.PRC, then if allowed by the user and the system, set TCB.PRC<-SEG.PRC. If not allowed, send a reset and return:
<SEQ=SEG.ACK><CTL=RST>
  • If the SEG.PRC is less than the TCB.PRC, then continue.
  • Set RCV.NXT to SEG.SEQ+1, IRS is set to SEG.SEQ, and any other control or text should be queued for processing later. ISS should be selected and a SYN segment sent of the form:
<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
  • SND.NXT is set to ISS+1 and SND.UNA to ISS. The connection state should be changed to SYN-RECEIVED. Note that any other incoming control or data (combined with SYN) will be processed in the SYN-RECEIVED state, but processing of SYN and ACK should not be repeated. If the listen was not fully specified (i.e., the foreign socket was not fully specified), then the unspecified fields should be filled in now. ๐Ÿคฉ
  • Fourth, other text or control. Any other control or text-bearing segment (not containing SYN) must have an ACK and thus would be discarded by the ACK processing. An incoming RST segment could not be valid, since it could not have been sent in response to anything sent by this incarnation of the connection. So you are unlikely to get here, but if you do, drop the segment, and return. ๐Ÿซ 

If the state is SYN-SENT then ๐Ÿค

  • First, check the ACK bit.
    • If the ACK bit is set:
      • If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send a reset (unless the RST bit is set, in which case drop the segment and return):
<SEQ=SEG.ACK><CTL=RST>
  • and discard the segment. Return.
  • If SND.UNA =< SEG.ACK =< SND.NXT then the ACK is acceptable. โœ…
  • Second, check the RST bit.
    • If the RST bit is set:
      • If the ACK was acceptable, then signal the user "error: connection reset", drop the segment, enter CLOSED state, delete the TCB, and return. Otherwise (no ACK) drop the segment and return.
  • Third, check the security and precedence.
    • If the security/compartment in the segment does not exactly match the security/compartment in the TCB, send a reset:
      • If there is an ACK:
<SEQ=SEG.ACK><CTL=RST>
  • Otherwise:
<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
  • If there is an ACK, the precedence in the segment must match the precedence in the TCB. If not, send a reset:
<SEQ=SEG.ACK><CTL=RST>
  • If there is no ACK:
    • If the precedence in the segment is higher than the precedence in the TCB, then if allowed by the user and the system, raise the precedence in the TCB to that in the segment. If not allowed to raise the prec, then send a reset:
<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
  • If the precedence in the segment is lower than the precedence in the TCB, continue.
  • If a reset was sent, discard the segment and return.
  • Fourth, check the SYN bit. This step should be reached only if the ACK is ok, or there is no ACK, and if the segment did not contain a RST.
    • If the SYN bit is on and the security/compartment and precedence are acceptable, then RCV.NXT is set to SEG.SEQ+1, and IRS is set to SEG.SEQ. SND.UNA should be advanced to equal SEG.ACK (if there is an ACK), and any segments on the retransmission queue which are thereby acknowledged should be removed.
    • If SND.UNA > ISS (our SYN has been ACKed), change the connection state to ESTABLISHED, form an ACK segment:
<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
  • and send it. Data or controls which were queued for transmission may be included. If there are other controls or text in the segment, then continue processing at the sixth step below, where the URG bit is checked. Otherwise return.
  • Otherwise, enter SYN-RECEIVED, form a SYN,ACK segment:
<SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
  • and send it. If there are other controls or text in the segment, queue them for processing after the ESTABLISHED state has been reached, return.
  • Fifth, if neither of the SYN or RST bits is set, then drop the segment and return. ๐Ÿ—‘๏ธ

Otherwise, ๐ŸŒŠ

First, check the sequence number. ๐Ÿ”ข

  • For the following states: SYN-RECEIVED STATE, ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE, CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, and TIME-WAIT STATE:
    • Segments are processed in sequence. Initial tests on arrival are used to discard old duplicates, but further processing is done in SEG.SEQ order. If a segment's contents straddle the boundary between old and new, only the new parts should be processed.
    • There are four cases for the acceptability test for an incoming segment:
Segment Receive  Test
Length  Window
------- -------  -------------------------------------------

   0       0     SEG.SEQ = RCV.NXT

   0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND

  >0       0     not acceptable

  >0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
              or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
  • If the RCV.WND is zero, no segments will be acceptable, but special allowance should be made to accept valid ACKs, URGs and RSTs.
  • If an incoming segment is not acceptable, an acknowledgment should be sent in reply (unless the RST bit is set, in which case drop the segment and return):
<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
  • After sending the acknowledgment, drop the unacceptable segment and return.
  • In the following, it is assumed that the segment is the idealized segment that begins at RCV.NXT and does not exceed the window. One could tailor actual segments to fit this assumption by trimming off any portions that lie outside the window (including SYN and FIN), and only processing further if the segment then begins at RCV.NXT. Segments with higher beginning sequence numbers may be held for later processing. ๐Ÿงฉ

Second, check the RST bit. ๐Ÿšจ

  • SYN-RECEIVED STATE
    • If the RST bit is set:
      • If this connection was initiated with a passive OPEN (i.e., came from the LISTEN state), then return this connection to LISTEN state and return. The user need not be informed. If this connection was initiated with an active OPEN (i.e., came from SYN-SENT state), then the connection was refused, so signal the user "connection refused". In either case, all segments on the retransmission queue should be removed. And in the active OPEN case, enter the CLOSED state, delete the TCB, and return.
  • ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, and CLOSE-WAIT
    • If the RST bit is set, then any outstanding RECEIVEs and SEND should receive "reset" responses. All segment queues should be flushed. Users should also receive an unsolicited general "connection reset" signal. Enter the CLOSED state, delete the TCB, and return. Yikes, that's a full reset ๐Ÿ˜ญ
  • CLOSING STATE, LAST-ACK STATE, and TIME-WAIT
    • If the RST bit is set, then enter the CLOSED state, delete the TCB, and return.

Third, check security and precedence. ๐Ÿ”

  • SYN-RECEIVED
    • If the security/compartment and precedence in the segment do not exactly match the security/compartment and precedence in the TCB, then send a reset, and return.
  • ESTABLISHED STATE
    • If the security/compartment and precedence in the segment do not exactly match the security/compartment and precedence in the TCB, then send a reset. Any outstanding RECEIVEs and SEND should receive "reset" responses. All segment queues should be flushed. Users should also receive an unsolicited general "connection reset" signal. Enter the CLOSED state, delete the TCB, and return. Security mismatch = full stop ๐Ÿ›‘

Okay so this check sits right after the sequence check, and that's giving intention ๐Ÿ’… It stops a segment from an old connection between these same ports (but with a different security or precedence) from knocking out the current connection. Iconic protection, no notes ๐Ÿ›ก๏ธ

Fourth, check the SYN bit. ๐Ÿฆ‹

This happens in these states:

  • SYN-RECEIVED
  • ESTABLISHED STATE
  • FIN-WAIT STATE-1
  • FIN-WAIT STATE-2
  • CLOSE-WAIT STATE
  • CLOSING STATE
  • LAST-ACK STATE
  • TIME-WAIT STATE

If the SYN is in the window, it's an error ๐Ÿšจ So we send a reset, any outstanding RECEIVEs and SENDs get reset responses, every segment queue gets flushed, and the user gets an unsolicited general connection reset signal too. Then we enter CLOSED, delete the TCB, and return. Bye bye ๐Ÿ‘‹

If the SYN is not in the window, this step never gets reached, because an ack already went out back in the first step (the sequence number check) ๐Ÿงš

Fifth, check the ACK field. ๐Ÿ’–

If the ACK bit is off, drop the segment and return. Done and dusted ๐Ÿ’…

If the ACK bit is on, it depends on the state:

SYN-RECEIVED STATE โœจ

If SND.UNA =< SEG.ACK =< SND.NXT, then enter the ESTABLISHED state and keep processing.

If the segment's acknowledgment isn't acceptable, form a reset segment:

<SEQ=SEG.ACK><CTL=RST>

and send it. ๐Ÿ™ˆ

ESTABLISHED STATE ๐ŸŒธ

If SND.UNA < SEG.ACK =< SND.NXT, then set SND.UNA <- SEG.ACK. Any segments on the retransmission queue that are now fully acknowledged get removed. Users should get positive acknowledgments for buffers that were SENT and fully acknowledged, so the SEND buffer comes back with an "ok" response. If the ACK is a duplicate (SEG.ACK < SND.UNA), you can ignore it. If the ACK is for something not yet sent (SEG.ACK > SND.NXT), then send an ACK, drop the segment, and return. Not it, bestie ๐Ÿ™…โ€โ™€๏ธ

If SND.UNA < SEG.ACK =< SND.NXT, the send window should be updated. If (SND.WL1 < SEG.SEQ or (SND.WL1 = SEG.SEQ and SND.WL2 =< SEG.ACK)), then set SND.WND <- SEG.WND, set SND.WL1 <- SEG.SEQ, and set SND.WL2 <- SEG.ACK. ๐ŸŽ€

Quick note: SND.WND is an offset from SND.UNA. SND.WL1 records the sequence number of the last segment used to update SND.WND, and SND.WL2 records the acknowledgment number of that same segment. The check is what stops old segments from messing with the window. Protected, obsessed ๐Ÿ˜ญ

FIN-WAIT-1 STATE ๐Ÿฆ‹

Do everything the ESTABLISHED state does, and then, if our FIN is now acknowledged, enter FIN-WAIT-2 and keep processing there โœจ

FIN-WAIT-2 STATE ๐ŸŒˆ

Do everything the ESTABLISHED state does, plus this: if the retransmission queue is empty, the user's CLOSE can be acknowledged with "ok", but don't delete the TCB yet ๐Ÿซถ

CLOSE-WAIT STATE ๐Ÿ’…

Same processing as the ESTABLISHED state. Easy ๐Ÿ’œ

CLOSING STATE ๐Ÿ”ฅ

Do everything the ESTABLISHED state does, and if the ACK acknowledges our FIN, enter the TIME-WAIT state. Otherwise, ignore the segment. Literally no drama ๐Ÿ™„

LAST-ACK STATE ๐Ÿ‘‘

The only thing that can show up in this state is an acknowledgment of our FIN. If our FIN is now acknowledged, delete the TCB, enter the CLOSED state, and return. Goodbye, TCB ๐Ÿฅ€

TIME-WAIT STATE โญ

The only thing that can show up here is a retransmission of the remote FIN. Acknowledge it and restart the 2 MSL timeout. โณ

Sixth, check the URG bit. ๐Ÿ“

ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE ๐ŸŒธ

If the URG bit is set, RCV.UP <- max(RCV.UP,SEG.UP). Signal the user that the remote side has urgent data if the urgent pointer (RCV.UP) is ahead of the data already consumed. If the user has already been signaled (or is still in "urgent mode") for this continuous run of urgent data, don't signal them again. Nobody likes being pinged twice ๐Ÿ˜Œ

CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT ๐Ÿ™ˆ

This shouldn't happen, since a FIN has already come in from the remote side. Ignore the URG.

Seventh, process the segment text. ๐Ÿง

ESTABLISHED STATE, FIN-WAIT-1 STATE, FIN-WAIT-2 STATE ๐Ÿ’–

Once we're in the ESTABLISHED state, segment text can be delivered into the user's RECEIVE buffers. Text can be moved into buffers until the buffer is full or the segment is empty. If the segment empties and carries a PUSH flag, the user gets told, when the buffer comes back, that a PUSH was received ๐Ÿ“ฃ

When TCP takes responsibility for delivering the data to the user, it must also acknowledge that it received the data. โœ…

Once TCP takes responsibility for the data, it advances RCV.NXT over the data it accepted and adjusts RCV.WND to match the current buffer availability. The total of RCV.NXT and RCV.WND should not go down. ๐Ÿ“‰โŒ

Please check out the window management suggestions in section 3.7. Trust me, they're worth it ๐ŸŽ€

Send an acknowledgment that looks like this:

<SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>

This ack should get piggybacked on a segment that's being transmitted, as long as that doesn't cause undue delay ๐Ÿฆ‹

CLOSE-WAIT STATE, CLOSING STATE, LAST-ACK STATE, TIME-WAIT STATE ๐Ÿ™ˆ

This shouldn't happen, since a FIN has already come in from the remote side. Ignore the segment text.

Eighth, check the FIN bit. ๐Ÿ‘‘

Don't process the FIN if the state is CLOSED, LISTEN, or SYN-SENT, because SEG.SEQ can't be validated there. Drop the segment and return. Not today ๐Ÿšซ

If the FIN bit is set, signal the user connection closing and return any pending RECEIVEs with that same message. Advance RCV.NXT over the FIN and send an acknowledgment for it. FIN implies PUSH for any segment text the user hasn't received yet, so that stuff is getting delivered ๐Ÿš€

SYN-RECEIVED STATE, ESTABLISHED STATE ๐ŸŒˆ

Enter the CLOSE-WAIT state. ๐Ÿ’…

FIN-WAIT-1 STATE ๐Ÿ’œ

If our FIN has been ACKed (maybe even in this very segment), enter TIME-WAIT, start the time-wait timer, and turn off the other timers. If not, enter the CLOSING state. โฐ

FIN-WAIT-2 STATE โญ

Enter the TIME-WAIT state. Start the time-wait timer and turn off the other timers. ๐Ÿงš

CLOSE-WAIT STATE ๐Ÿซถ

Stay in the CLOSE-WAIT state. ๐ŸŒธ

CLOSING STATE ๐Ÿฅ€

Stay in the CLOSING state. ๐Ÿ™ƒ

LAST-ACK STATE ๐ŸŒ™

Stay in the LAST-ACK state. ๐Ÿ’ค

TIME-WAIT STATE โณ

Stay in the TIME-WAIT state, and restart the 2 MSL time-wait timeout. โœจ

And return. ๐ŸŽ€


USER TIMEOUT โฐ

For any state, if the user timeout expires, flush all queues. Signal the user error: connection aborted due to user timeout in general, and for any outstanding calls too. Then delete the TCB, enter the CLOSED state, and return. Oof ๐Ÿ˜ญ

RETRANSMISSION TIMEOUT ๐Ÿ”

For any state, if the retransmission timeout expires on a segment in the retransmission queue, send the segment at the front of that queue again, reinitialize the retransmission timer, and return. Second chances are everything ๐Ÿซถ

TIME-WAIT TIMEOUT ๐ŸŒ™

If the time-wait timeout expires on a connection, delete the TCB, enter the CLOSED state, and return. And that's the tea โ˜•


GLOSSARY ๐Ÿ“š

1822 ๐Ÿงพ

BBN Report 1822, "The Specification of the Interconnection of a Host and an IMP". The specification of the interface between a host and the ARPANET.

ACK ๐Ÿฆ‹

A control bit (acknowledge) that takes up no sequence space. It shows that this segment's acknowledgment field holds the next sequence number the sender expects to receive, which means it's acknowledging receipt of all the earlier sequence numbers. Simple, but so important ๐Ÿ’–

ARPANET message ๐Ÿ’Œ

The unit of transmission between a host and an IMP in the ARPANET. The maximum size is about 1012 octets (8096 bits).

ARPANET packet ๐Ÿ“ฆ

A unit of transmission used inside the ARPANET between IMPs. The maximum size is about 126 octets (1008 bits).

connection ๐Ÿ”—

A logical communication path identified by a pair of sockets. โœจ

datagram ๐Ÿ“จ

A message sent in a packet switched computer communications network.

Destination Address ๐Ÿ“

The destination address, usually the network and host identifiers.

FIN ๐Ÿ

A control bit (finis) that takes up one sequence number. It shows that the sender won't send any more data or control that uses sequence space. Bye for real ๐Ÿ‘‹

fragment ๐Ÿงฉ

A portion of a logical unit of data. In particular, an internet fragment is a portion of an internet datagram.

FTP ๐Ÿ“

A file transfer protocol.

header ๐ŸŽ€

Control information at the beginning of a message, segment, fragment, packet, or block of data.

host ๐Ÿ–ฅ๏ธ

A computer. In particular, a source or destination of messages from the point of view of the communication network. ๐Ÿ’ป

Identification ๐Ÿชช

An Internet Protocol field. The sender assigns this value, and it helps put the fragments of a datagram back together ๐Ÿงท

IMP ๐Ÿ”€

The Interface Message Processor, which is the packet switch of the ARPANET.

internet address ๐Ÿ 

A source or destination address specific to the host level.

internet datagram ๐Ÿ“ฌ

The unit of data exchanged between an internet module and the higher level protocol, together with the internet header.

internet fragment ๐Ÿงฉ

A portion of the data of an internet datagram, with an internet header.

IP ๐ŸŒ

Internet Protocol.

IRS ๐ŸŒฑ

The Initial Receive Sequence number. The first sequence number used by the sender on a connection.

ISN ๐ŸŒŸ

The Initial Sequence Number. The first sequence number used on a connection (either ISS or IRS). It's selected using a clock-based procedure. โฐ

ISS ๐ŸŒธ

The Initial Send Sequence number. The first sequence number used by the sender on a connection.

leader ๐Ÿšฉ

Control information at the beginning of a message or block of data. In particular, in the ARPANET, it's the control information on an ARPANET message at the host-IMP interface.

left sequence โฌ…๏ธ

The next sequence number to be acknowledged by the data receiving TCP (or the lowest currently unacknowledged sequence number). It's sometimes called the left edge of the send window. ๐ŸชŸ

local packet ๐Ÿ˜๏ธ

The unit of transmission within a local network.

module ๐Ÿงฑ

An implementation, usually in software, of a protocol or other procedure. ๐Ÿ› ๏ธ

MSL โณ

Maximum Segment Lifetime: the time a TCP segment can exist in the internetwork system. It's arbitrarily defined to be 2 minutes. Long enough to be a whole era ๐Ÿ˜ญ

octet ๐Ÿ”ข

An eight bit byte.

Options โš™๏ธ

An Option field may contain several options, and each option may be several octets long. The options are mainly used in testing situations, for example, to carry timestamps. Both the Internet Protocol and TCP provide for options fields. ๐Ÿงช

packet ๐Ÿ“ฆ

A package of data with a header that may or may not be logically complete. It's more often a physical packaging than a logical one. ๐ŸŽ

port ๐Ÿšช

The part of a socket that specifies which logical input or output channel of a process is associated with the data. Basically the door the data walks through ๐Ÿšชโœจ

process ๐ŸŒธ A program in execution! It's a source or destination of data from the point of view of the TCP or other host-to-host protocol. โœจ

PUSH ๐Ÿ’… A control bit occupying no sequence space, indicating that this segment contains data that must be pushed through to the receiving user. ๐Ÿซถ

RCV.NXT ๐Ÿฆ‹ receive next sequence number RCV.UP ๐ŸŒˆ receive urgent pointer RCV.WND ๐ŸŽ€ receive window

receive next sequence number ๐Ÿงš This is the next sequence number the local TCP is expecting to receive. Literally the number it's waiting for, bestie. ๐Ÿ‘€

receive window ๐Ÿ’– This is the range of sequence numbers the local (receiving) TCP is willing to receive. So the local TCP treats any segment overlapping RCV.NXT to RCV.NXT + RCV.WND - 1 as carrying acceptable data or control. Anything with sequence numbers entirely outside that range is considered a duplicate and gets discarded. Bye, bye ๐Ÿ‘‹

RST ๐Ÿ’€ A control bit (reset) that occupies no sequence space. It tells the receiver to delete the connection without any further interaction. The receiver can look at the sequence number and acknowledgment fields of the incoming segment to decide whether to honor the reset or ignore it. ngl this is a big decision. In no case does receiving a segment containing RST trigger a RST in response, so nobody's starting a reset war here ๐Ÿ™…โ€โ™€๏ธ

RTP ๐Ÿ“ Real Time Protocol: a host-to-host protocol for communicating time critical information. โฐ

SEG.ACK ๐ŸŒธ segment acknowledgment SEG.LEN ๐Ÿฆ‹ segment length SEG.PRC ๐Ÿ‘‘ segment precedence value SEG.SEQ โœจ segment sequence SEG.UP ๐Ÿ”ฅ segment urgent pointer field SEG.WND ๐ŸŒˆ segment window field

segment ๐ŸŽ€ A logical unit of data. In particular, a TCP segment is the unit of data transferred between a pair of TCP modules. Main character energy ๐Ÿ’…

segment acknowledgment ๐Ÿซถ The sequence number in the acknowledgment field of the arriving segment.

segment length ๐Ÿ“ The amount of sequence number space a segment occupies, including any controls that take up sequence space.

segment sequence ๐Ÿงš The number in the sequence field of the arriving segment.

send sequence ๐Ÿ’œ This is the next sequence number the local (sending) TCP will use on the connection. It starts out selected from an initial sequence number curve (ISN) and goes up by one for each octet of data or sequenced control it transmits. Iykyk ๐Ÿ™ˆ

send window ๐ŸŒธ This is the range of sequence numbers the remote (receiving) TCP is willing to receive. It's the value of the window field in segments from that remote (data receiving) TCP. A TCP can emit new sequence numbers from SND.NXT up to SND.UNA + SND.WND - 1. (Retransmissions of sequence numbers between SND.UNA and SND.NXT are expected, of course. Obviously ๐Ÿ™„)

SND.NXT ๐Ÿฆ‹ send sequence SND.UNA ๐ŸŒˆ left sequence SND.UP ๐Ÿ’– send urgent pointer SND.WL1 โœจ segment sequence number at last window update SND.WL2 ๐ŸŽ€ segment acknowledgment number at last window update SND.WND ๐Ÿ‘‘ send window

socket ๐Ÿงš An address that specifically includes a port identifier. In other words, it's the concatenation of an Internet Address with a TCP port. ๐Ÿ”Œ

Source Address ๐Ÿ“ The source address, usually the network and host identifiers. ๐Ÿ“

SYN ๐Ÿ”ฅ A control bit in the incoming segment, occupying one sequence number. It's used at the initiation of a connection to indicate where the sequence numbering will start. Big first impression energy ๐Ÿ’…

TCB ๐Ÿ’œ Transmission control block: the data structure that records the state of a connection. It's the connection's whole diary ๐Ÿ““

TCB.PRC ๐Ÿ‘‘ The precedence of the connection.

TCP ๐ŸŒˆ Transmission Control Protocol: a host-to-host protocol for reliable communication in internetwork environments. The queen of reliability ๐Ÿ‘‘๐Ÿซถ

TOS ๐Ÿฆ‹ Type of Service, an Internet Protocol field.

Type of Service ๐ŸŽ€ An Internet Protocol field that indicates the type of service for this internet fragment.

URG ๐Ÿ’€ A control bit (urgent) occupying no sequence space. It's used to tell the receiving user to do urgent processing, as long as there's data to be consumed with sequence numbers less than the value in the urgent pointer. Emergency mode, bestie ๐Ÿšจ

urgent pointer ๐ŸŒธ A control field that's only meaningful when the URG bit is on. It communicates the value of the urgent pointer, which points at the data octet associated with the sending user's urgent call. ๐Ÿ“ฃ


REFERENCES ๐Ÿ“šโœจ

  • [1] Cerf, V., and R. Kahn, "A Protocol for Packet Network Intercommunication", IEEE Transactions on Communications, Vol. COM-22, No. 5, pp 637-648, May 1974.
  • [2] Postel, J. (ed.), "Internet Protocol - DARPA Internet Program Protocol Specification", RFC 791, USC/Information Sciences Institute, September 1981.
  • [3] Dalal, Y. and C. Sunshine, "Connection Management in Transport Protocols", Computer Networks, Vol. 2, No. 6, pp. 454-473, December 1978.
  • [4] Postel, J., "Assigned Numbers", RFC 790, USC/Information Sciences Institute, September 1981.
๐Ÿ“ฆ where this page comes from