Speaking of TCP's three-way handshake and four waved hands

Speaking of TCP's three-way handshake and four waved hands

Transmission Control Protocol (TCP, Transmission Control Protocol) is a connection-oriented, reliable, byte stream-based transport layer communication protocol.

The HTTP we are familiar with is based on TCP.

TCP connection is also a very high-frequency topic in interviews. The general interviewer's starting method is: please talk about TCP's three-way handshake/four-time wave...

The outline of this article is as follows, if you don’t finish it, you can collect it and watch it slowly.

  • Simple explanation of three handshake and four wave of hands
  • Advanced explanation of three handshake and four wave of hands
  • Why is the three-way handshake
  • Why wave four times
  • TCP message format
  • Slow start and congestion avoidance
  • Fast retransmission and fast recovery
  • When does time_wait appear, and how to deal with it when it appears in large numbers
  • When does close_wait appear, and how to deal with it when it appears in large numbers

getting Started

Entry-level answer, briefly describe what is going on between the client and the server each time.

It is the client that initiates the connection request, and the server that receives the connection request.

For several keywords in the figure, it is the flag in the control bit in the TCP message (1 means there is a corresponding flag)

  • SYN means to establish a connection
  • FIN means to close the connection
  • ACK means response

Three-way handshake (connection establishment, red part):

  1. The client sends a SYN packet to the server (let’s establish diplomatic relations)
  2. The server receives and sends an ACK + SYN packet (OK, let’s establish diplomatic relations)
  3. The client receives and sends an ACK packet (OK)

After completing these three steps, the client and the server establish a deep friendship, and begin to communicate with each other and transfer data. When the twins have nothing to say, the boat of friendship will turn upside down.

Wave four times (disconnected, green part):

  1. The client sends a FIN packet to the server (I will do everything to you)
  2. The server receives and sends an ACK packet (good, great)
  3. The server sends another FIN packet (I have nothing to say to you)
  4. The client sends an ACK packet to the server (well, you are also good)

The disconnection can be proposed by either party first, usually by the client.

Advanced

The above description is relatively simple, and we can explore the various behaviors between the client and the server in more depth.

  • SYN means to establish a connection
  • FIN means to close the connection
  • ACK means response
  • seq sequence number, which means our (sender) side, the first bit of the data part of this packet should be in the position in the entire data stream
  • Ack acknowledge number: indicates the next sequence number of the expected counterpart (receiver)

Three-way handshake (connection establishment, red part):

The server is in the listening state (LISTEN) and is ready to accept connections at any time.

  1. The client sends a SYN packet to the server, and uses a random number as the initial sequence number seq = x to enter the SYN_SENT state
  2. The server receives and sends an ACK + SYN packet, and a random number is also used as the initial sequence number seq = y, and enters the SYN_RCVD state
  3. The client receives and sends an ACK packet (OK) and enters the ESTABLISHED state, indicating that the connection is established
  4. The server also enters the ESTABLISHED state after receiving the ACK, indicating that the connection is established

After completing these four steps (just a description of the state change, or a three-way handshake), the client and the server once again establish a deep friendship, start to communicate with each other and pass data.

Of course, there is always a feast in the world, and the time to wave goodbye is coming.

Wave four times (disconnected, green part):

Or the client proposes to break up first.

  1. The client sends a FIN packet to the server and enters the FIN_WAIT1 state
  2. The server receives and sends an ACK packet and enters the CLOSE_WAIT state
  3. The server sends another FIN packet to enter the LAST_ACK state
  4. The client sends an ACK packet to the server, enters the TIME_WAIT state, and waits for 2MSL (message maximum survival time) to become the CLOSED state
  5. The server also changes to the CLOSED state after receiving the ACK

Expand

For the process described above, if you don't know much about it before, you will definitely have some questions about some points.

The following summarizes some issues that can be extended.

Why is a three-way handshake required to establish a connection

Why is it three, not two, or four? Use classic phone calls to help understand.

  • The first handshake: A said to B, B, can you hear it? (SYN)
  • 2.handshake: B says to A, can hear it (ACK), can you hear it? (SYN)
  • The third handshake: A said to B, I am the same! (ACK)

After the three handshake, A and B can be sure of such a thing: what I say, you can hear; what you say, I can also hear. In this way, you can start to communicate happily.

  • If it is twice, then B cannot determine whether B’s message A can be received, and perhaps B’s message A cannot be received.
  • If four times, yes, but not necessary.

Why does it take four waves to disconnect

Why can't it be three times like establishing a connection? After all, you can guarantee to know each other three times.

Looking back at the above figure, you can see that after the server knows that the client wants to disconnect, it first sends an ACK packet to the client, and then sends a FIN packet. The key to the problem is whether the two steps can be combined. If you can, it can be reduced to three waves.

The answer is of course no. Because when the server learns that the client wants to disconnect, it may still have some things left unfinished, for example, there are still some messages that haven't been sent (I still have something to say about the series). After it is processed, send a FIN packet to the client, indicating that it can also end. This is the client sending an ACK packet to the server, indicating that he knows it.

TCP message format

This question was asked during the interview. At that time, I confidently and smoothly finished the TCP connection process, and even silently gave myself a thumbs-up. . . Don't talk about it later.

TCP's message structure is still a bit complicated. I won't discuss it here. I found a picture on the Internet (see the watermark for the source).

You can see that there have been FIN, ACK, SYN and other things that have appeared above, and these have corresponding positions in the message.

Slow start and congestion avoidance

The sender maintains a state variable called the congestion window cwnd (congestion window). The size of the congestion window depends on the degree of network congestion and changes dynamically. The sender makes its own sending window equal to the congestion window. In addition, considering the receiver's receiving capability, the sending window may be smaller than the congestion window.

Fast retransmission and fast recovery

Fast retransmission

As long as the sender receives three repeated acknowledgments in a row, it should immediately retransmit the message segment that the other party has not received, instead of waiting for the set retransmission timer to expire.

Quick recovery

  1. When the sender receives three repeated acknowledgments in a row, it executes the "multiply reduction" algorithm to halve the ssthresh threshold. But then the slow start algorithm is not executed.
  2. Considering that if the network is congested, it will not receive several repeated confirmations, so the sender now believes that the network may not be congested. Therefore, the slow start algorithm is not executed at this time, but the cwnd is set to the size of ssthresh, and then the congestion avoidance algorithm is executed

When does time_wait appear, how to discover and deal with it when it appears

Timewait is the state that the party that actively closes will appear. When it receives the FIN packet from the other party and returns an ACK, it enters timewait.

There are two reasons for the existence of time_wait

  1. Reliably terminate the connection: if the client in timewait sends the server to confirm that the segment is lost, the server will send the FIN segment again here, then the client must be in a receivable state that is timewait instead of close.
  2. Ensure that the late message segment has enough time to be recognized and discarded: a TCP port in linux cannot be opened twice or more. When the client is in the timewait state, we will not be able to use this port to establish a new connection. Assuming there is no timewait state, the new connection may receive data from the old connection.

Scenarios where timewait occurs in large numbers are generally on the server side, because a large number of clients connect to a few servers. Although it is generally the client that actively disconnects, in some cases it may be that the client sends a message to the server, and then the server actively shuts down. This may cause a large number of timewait states on the server side in a short period of time, and occupy resources so that more sockets cannot be created.

Several solutions:

  1. Change to long link
  2. When designing, try to let the client actively close
  3. Reuse the port, that is, the server sets the SOREUSEADDR socket option to notify the kernel that if the port is busy, but the TCP connection is in the TIMEWAIT state, the port can be reused
  4. Increase IP

When does close_wait appear, and how to deal with it when it appears in large numbers

Close_wait is the state of the passively closed party. When the cause occurs, after receiving the signal to close, there are still some things on your side that have not been processed, resulting in the delay in sending the FIN packet to the actively disconnected party.

Therefore, in general, a large number of problems are caused by our program, and it is recommended to change the code.

You can view the number of connections in various states through the netstat command, for example:

➜ ~ netstat -an|awk'/tcp/{print $6}'|sort|uniq -c
   1 CLOSED
   8 CLOSE_WAIT
   1 CLOSING
  42 ESTABLISHED
   1 FIN_WAIT_1
   2 FIN_WAIT_2
   2 LAST_ACK
  20 LISTEN
   3 SYN_SENT
   1 com.apple.network.tcp_ccdebug