Applications that “live” above the transport layer use the socket API to send and receive data over networks. For applications using TCP, calls to the socket API cause the socket to transition between the states in the TCP state diagram:
TCP starts with connection establishment. Of the two communication endpoints, one will listen
for incoming connections and the other will use connect
to initiate the connection. The host that listens is known as the server, and the host that initiates the connection is called the client. In the diagram above, the heavy solid lines show the path typically taken by the client, and the dashed lines show the path typically taken by the server.
First, the server should:
bind
to the local IP address and TCP port that the socket should use, and listen
for incoming connections on the socket. This is the “passive open” step shown on the diagram. Nothing is sent on the network but the socket is now in the LISTEN
state.accept
, which won’t send anything over the network, but will wait until there is an incoming connection. When a connection is initiated by the client, accept
will spin off a new socket which will be used for the connection to this host.The client will then:
bind
to the local IP address and TCP port. This is optional - if there is no explicit call to bind
, the operating system will assign a TCP port to this socket in the next step.connect
, specifying the destination IP address and port. This is the “active open” step shown on the diagram, and starts the three-way TCP handshake. A SYN is sent from the client to the server, putting the client in SYN_SENT
state. The server receives the SYN and responds with a message carrying its own SYN and an ACK of the client’s SYN, putting it in SYN_RCVD
state. The client receives the SYN ACK, sends an ACK, and goes to ESTABLISHED
state.Once connection establishment is complete, the client and server applications can use two more socket API calls to transfer data while remaining in the ESTABLISHED
state:
send
to put data into the send socket buffer, from which the OS will stream data across the connection. As soon as a data segment is delivered to the receive socket buffer at the other endpoint, an ACK is sent in response.recv
to read data from the receive socket buffer.Finally, the client or server can use the shutdown
socket API call to send a FIN to the other endpoint, and close the connection. Either side can initiate the shutdown, but we’ll describe the scenario where the client initiates the shutdown.
shutdown
, and sends a FIN over the network. The client is in FIN_WAIT_1
state. The server receives the FIN and sends an ACK, at which point the server is in CLOSE_WAIT
state. When the ACK is received by the client, the client is in FIN_WAIT_2
state.CLOSE_WAIT
state calls shutdown
, sending its own FIN. The client receives the FIN and sends an ACK, putting it in TIME_WAIT
state; after some time elapses, the connection will be closed. The server receives the ACK, and closes its connection.