TCP's three-way handshake (to establish a connection) and four-way wave (to close the connection)

The transport control protocol of the carrier layer, which provides reliable connection services, uses three-way handshake confirmation to establish a connection:

The bit code is the tcp flag bit, and there are 6 kinds of signs:

SYN (synchronous establishment of connection)

ACK (acknowledgement confirmation)

PSH (push transmission)

FIN (finish end)

RST (reset reset)

URG (urgent emergency)

Sequence number

Acknowledge number

Client TCP state migration:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
Server TCP state migration:
CLOSED->LISTEN->SYN received->ESTABLISHED->CLOSE_WAIT->LAST_ACK-> CLOSED

 

The meaning of each state is as follows: 
LISTEN - listen for connection requests from remote TCP ports; 
SYN-SENT - wait for a matching connection request after sending a connection request; 
SYN-RECEIVED - wait for a connection request after receiving and sending a connection request acknowledgment; 
ESTABLISHED - represents an open connection, data can be transferred to the user; 
FIN-WAIT-1 - waiting for a connection interruption request from the remote TCP, or an acknowledgment of a previous connection interruption request;
FIN-WAIT-2 - waiting from the remote TCP Connection interruption request; 
CLOSE-WAIT - waiting for the connection interruption request sent from the local user; 
CLOSING - waiting for the confirmation of the connection interruption by the remote TCP; 
LAST-ACK - waiting for the confirmation of the connection interruption request originally sent to the remote TCP; 
TIME-WAIT - waits enough time to ensure that the remote TCP receives an acknowledgment of the connection break request; 
CLOSED - no connection status is present;

 

In the TCP/IP protocol, the TCP protocol provides reliable connection services, and uses a three-way handshake to establish a connection, as shown in Figure 1.

(1) The first handshake: When the connection is established, client A sends a SYN packet (SYN=j) to server B, and enters the SYN_SEND state, waiting for server B to confirm.

(2) The second handshake: Server B receives the SYN packet, and must confirm the SYN of client A (ACK=j+1), and also sends a SYN packet (SYN=k), that is, SYN+ACK packet, at this time Server B enters the SYN_RECV state.

(3) The third handshake: Client A receives the SYN+ACK packet from server B, and sends an acknowledgment packet ACK (ACK=k+1) to server B. After the packet is sent, client A and server B enter the ESTABLISHED state and complete. Three handshake.

After completing the three-way handshake, the client and server begin to transmit data.

Acknowledgment number: Its value is equal to the sender's sending sequence number + 1 (that is, the next sequence number that the receiver expects to receive).

Figure 1 TCP three-way handshake to establish a connection  

TCP header structure:
source port 16 bits
destination port 16 bits
sequence number 32 bits
response sequence number 32 bits
TCP header length 4 bits
reserved 6 bits
control code 6 bits
window size 16 bits
offset 16 bits
checksum 16 bits
option 32 bits (Optional)
This gives us the minimum length of the TCP header, which is 20 bytes

  • The first handshake: The
    client sends a packet with the SYN flag of TCP at 1 indicating the port of the server to which the client intends to connect, and the initial sequence number X, which is stored in the Sequence Number field of the packet header.
<iframe id="iframe_0.36920690326951444" style="border-style: none; border-width: initial; width: 0px; height: 0px;" src="data:text/html;charset=utf8,%3Cstyle%3Ebody%7Bmargin:0;padding:0%7D%3C/style%3E%3Cimg%20id=%22img%22%20src=%22http://blogimg.chinaunix.net/blog/upfile2/100327002911.png?_=3535612%22%20style=%22border:none;max-width:1323px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.36920690326951444',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no"></iframe>
  • Second handshake: The
    server sends back an acknowledgment (ACK) response. That is, the SYN flag bit and the ACK flag bit are both 1. At the same time, the Acknowledgement Number (Acknowledgement Number) is set to the customer's ISN plus 1 to. That is, X+1.

 

<iframe id="iframe_0.9267806357238442" style="border-style: none; border-width: initial; width: 0px; height: 0px;" src="data:text/html;charset=utf8,%3Cstyle%3Ebody%7Bmargin:0;padding:0%7D%3C/style%3E%3Cimg%20id=%22img%22%20src=%22http://blogimg.chinaunix.net/blog/upfile2/100327003054.png?_=3535612%22%20style=%22border:none;max-width:1323px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.9267806357238442',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no"></iframe>

  • The third handshake. The
    client sends an acknowledgment packet (ACK) again, the SYN flag is 0, and the ACK flag is 1. And the sequence number field of the ACK sent by the server +1 is placed in the confirmation field and sent to the other party. And in the data +1 for the segment to write the ISN
<iframe id="iframe_0.8200425617396832" style="border-style: none; border-width: initial; width: 0px; height: 0px;" src="data:text/html;charset=utf8,%3Cstyle%3Ebody%7Bmargin:0;padding:0%7D%3C/style%3E%3Cimg%20id=%22img%22%20src=%22http://blogimg.chinaunix.net/blog/upfile2/100327003214.png?_=3535612%22%20style=%22border:none;max-width:1323px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.8200425617396832',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no"></iframe>
The following is a specific example screenshot :
1. This figure contains two parts of information: TCP's three-way handshake (content in the box) (SYN, (SYN+ACK), ACK)
2. TCP data transmission ([TCP segment of a reassembled PUD]) It can be seen that the server transmits the message packets in segments by the data TCP layer
(1) After the server side receives the HTTP request such as GET, it constructs a response message, which carries the content of the web page, and sends the message 200 OK at the HTTP layer of the server side -> the TCP layer of the server side; 
(2) The TCP layer of the server side divides the message packet. Fragment transmission; 
(3) The TCP layer on the client side sends back a response to each message packet received in fragments; 
(4) The TCP layer on the client side will confirm with ACK every time it receives a part, and then the server continues to transmit, and the client continues to confirm until it is completed. After responding to all the fragments of the message, the server sends a combined HTTP response packet of 200 OK, at which time the message packet of HTTP 200 OK can be displayed in the message tracking of the client side

 

Close the connection:

 

Since TCP connections are full-duplex, each direction must be closed individually. The principle is that when a party completes its data transmission task, it can send a FIN to terminate the connection in this direction. Receiving a FIN only means that there is no data flow in this direction, a TCP connection can still send data after receiving a FIN. The side that shuts down first will perform an active shutdown, while the other side performs a passive shutdown.

 The teardown of the CP's connection requires four packets to be sent, hence the name four-way handshake. Either the client or the server can actively initiate a hand-waving action. In socket programming, either party can perform a close() operation to generate a hand-waving action.

(1) Client A sends a FIN to close the data transfer from client A to server B. 

(2) Server B receives this FIN, and it sends back an ACK, confirming that the sequence number is the received sequence number plus 1. Like SYN, a FIN will occupy a sequence number. 

(3) Server B closes the connection with client A and sends a FIN to client A. 

(4) Client A sends an ACK message confirmation, and sets the confirmation sequence number to the received sequence number plus 1. 

TCP uses four waves to close the connection as shown in Figure 2.

 Figure 2 TCP waves four times to close the connection

 

See Wireshark for packet capture. The measured packet capture results are not strictly in accordance with the wave sequence. I guess the time interval is too short.

<iframe id="iframe_0.5372582839336246" style="border-style: none; border-width: initial; width: 20px; height: 20px;" src="data:text/html;charset=utf8,%3Cstyle%3Ebody%7Bmargin:0;padding:0%7D%3C/style%3E%3Cimg%20id=%22img%22%20src=%22http://blogimg.chinaunix.net/blog/upfile2/100327023334.png?_=3535612%22%20style=%22border:none;max-width:1323px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.5372582839336246',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no"></iframe>
 

In-depth understanding of the release of TCP connections : 

 

Since TCP connections are full-duplex, each direction must be closed individually. The principle is that when a party completes its data transmission task, it can send a FIN to terminate the connection in this direction. Receiving a FIN only means that there is no data flow in this direction, a TCP connection can still send data after receiving a FIN. The side that shuts down first will perform an active shutdown, while the other side performs a passive shutdown.
The connection of the TCP protocol is a full-duplex connection, and a TCP connection has a bidirectional read and write channel. 
In short, it is "first off reading, then off writing", a total of four stages are required. Take the client to close the connection as an example:
1. The server read channel is closed
2. The client write channel is closed
3. The client read channel is closed
4. The server write channel is closed
The closing behavior is to send a FIN (finish) data segment. Until the FIN sent by the other party is received, and the other party has received the acknowledgment ACK, the data communication between the two parties is completely ended, and the confirmation data segment ACK needs to be returned for each reception in the process.
Detailed process: In
    the first stage    , after the client sends the data, it sends a FIN data segment to the server, the serial number is i ;
    1. After the server receives FIN(i) , it returns the confirmation segment ACK , the serial number is i+1 , close The server reads the channel ;
    2. After the client receives the ACK(i+1) , it closes the client's write channel ;
   (At this time, the client can still read the server's data through the read channel, and the server can still write the data through the write channel) After the server sends the data in the
    second stage  , it sends a FIN data segment to the client with the serial number j;
    3 . After the client receives FIN(j) , it returns the confirmation segment ACK , the serial number is j+1 , and closes the client read channel ;
    4. After the server receives ACK(j+1) , closes the server write channel .
This is a standard TCP shutdown in two phases, both server and client can initiate shutdown, completely symmetrical.
The FIN flag is set when the last piece of data is sent. In the standard example, the server is still sending data, so it is necessary to wait until the end of sending, and set FIN (this time can be called the TCP connection is in a half-closed state, because the data is still available . transfer from the passively closed side to the actively closed side). If there is no data to send when the server receives FIN(i), you can set the FIN(j) flag when returning ACK(i+1), which is equivalent to combining the second and third steps.
Read the chapter on closing TCP connections in "Linux Network Programming" and make the following notes:

TIME_WAIT and Close_Wait status of TCP

 

面试时看到应聘者简历中写精通网络,TCP编程,我常问一个问题,TCP建立连接需要几次握手?95%以上的应聘者都能答对是3次。问TCP断开连接需要几次握手,70%的应聘者能答对是4次通讯。再问CLOSE_WAIT,TIME_WAIT是什么状态,怎么产生的,对服务有什么影响,如何消除?有一部分同学就回答不上来。不是我扣细节,而是在通讯为主的前端服务器上,必须有能力处理各种TCP状态。比如统计在本厂的一台前端机上高峰时间TCP连接的情况,统计命令:

 

 

  1. netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'  

 

 

结果:

<iframe id="iframe_0.8287450934294611" style="border-style: none; border-width: initial; width: 186px; height: 217px;" src="data:text/html;charset=utf8,%3Cstyle%3Ebody%7Bmargin:0;padding:0%7D%3C/style%3E%3Cimg%20id=%22img%22%20src=%22http://dl.iteye.com/upload/attachment/0077/6054/84326b90-3259-337a-84c9-1051ac366772.jpg?_=3535612%22%20style=%22border:none;max-width:1323px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.8287450934294611',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no"></iframe>

 

除了ESTABLISHED,可以看到连接数比较多的几个状态是:FIN_WAIT1, TIME_WAIT, CLOSE_WAIT, SYN_RECV和LAST_ACK;下面的文章就这几个状态的产生条件、对系统的影响以及处理方式进行简单描述。

 

TCP状态

TCP状态如下图所示:
<iframe id="iframe_0.31398083595559" style="border-style: none; border-width: initial; width: 1012px; height: 1115px;" src="data:text/html;charset=utf8,%3Cstyle%3Ebody%7Bmargin:0;padding:0%7D%3C/style%3E%3Cimg%20id=%22img%22%20src=%22http://dl.iteye.com/upload/attachment/0077/6056/bdf8d214-c8de-3b2a-8a53-219a0dce3259.png?_=3535612%22%20style=%22border:none;max-width:1323px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.31398083595559',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no"></iframe>

可能有点眼花缭乱?再看看这个时序图


<iframe id="iframe_0.28924990841187537" style="border-style: none; border-width: initial; width: 645px; height: 605px;" src="data:text/html;charset=utf8,%3Cstyle%3Ebody%7Bmargin:0;padding:0%7D%3C/style%3E%3Cimg%20id=%22img%22%20src=%22http://dl.iteye.com/upload/attachment/0077/6058/5d4e8c89-fc42-3862-bdb8-399bc982f410.png?_=3535612%22%20style=%22border:none;max-width:1323px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.28924990841187537',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no"></iframe>

 

下面看下大家一般比较关心的三种TCP状态

SYN_RECV 

服务端收到建立连接的SYN没有收到ACK包的时候处在SYN_RECV状态。有两个相关系统配置:

 

1,net.ipv4.tcp_synack_retries :INTEGER

默认值是5

对于远端的连接请求SYN,内核会发送SYN + ACK数据报,以确认收到上一个 SYN连接请求包。这是所谓的三次握手( threeway handshake)机制的第二个步骤。这里决定内核在放弃连接之前所送出的 SYN+ACK 数目。不应该大于255,默认值是5,对应于180秒左右时间。通常我们不对这个值进行修改,因为我们希望TCP连接不要因为偶尔的丢包而无法建立。

2,net.ipv4.tcp_syncookies

一般服务器都会设置net.ipv4.tcp_syncookies=1来防止SYN Flood攻击。假设一个用户向服务器发送了SYN报文后突然死机或掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级(大约为30秒-2分钟)。

 

这些处在SYNC_RECV的TCP连接称为半连接,并存储在内核的半连接队列中,在内核收到对端发送的ack包时会查找半连接队列,并将符合的requst_sock信息存储到完成三次握手的连接的队列中,然后删除此半连接。大量SYNC_RECV的TCP连接会导致半连接队列溢出,这样后续的连接建立请求会被内核直接丢弃,这就是SYN Flood攻击。

 

能够有效防范SYN Flood攻击的手段之一,就是SYN Cookie。SYN Cookie原理由D. J. Bernstain和 Eric Schenk发明。SYN Cookie是对TCP服务器端的三次握手协议作一些修改,专门用来防范SYN Flood攻击的一种手段。它的原理是,在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值。在收到TCP ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。

 

观测服务上SYN_RECV连接个数为:7314,对于一个高并发连接的通讯服务器,这个数字比较正常。

CLOSE_WAIT

发起TCP连接关闭的一方称为client,被动关闭的一方称为server。被动关闭的server收到FIN后,但未发出ACK的TCP状态是CLOSE_WAIT。出现这种状况一般都是由于server端代码的问题,如果你的服务器上出现大量CLOSE_WAIT,应该要考虑检查代码。

TIME_WAIT

根据TCP协议定义的3次握手断开连接规定,发起socket主动关闭的一方 socket将进入TIME_WAIT状态。TIME_WAIT状态将持续2个MSL(Max Segment Lifetime),在Windows下默认为4分钟,即240秒。TIME_WAIT状态下的socket不能被回收使用. 具体现象是对于一个处理大量短连接的服务器,如果是由服务器主动关闭客户端的连接,将导致服务器端存在大量的处于TIME_WAIT状态的socket, 甚至比处于Established状态下的socket多的多,严重影响服务器的处理能力,甚至耗尽可用的socket,停止服务。

 

为什么需要TIME_WAIT?TIME_WAIT是TCP协议用以保证被重新分配的socket不会受到之前残留的延迟重发报文影响的机制,是必要的逻辑保证。

 

和TIME_WAIT状态有关的系统参数有一般由3个,本厂设置如下:

net.ipv4.tcp_tw_recycle = 1

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_fin_timeout = 30

 

net.ipv4.tcp_fin_timeout,默认60s,减小fin_timeout,减少TIME_WAIT连接数量。

 

net.ipv4.tcp_tw_reuse = 1表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;

net.ipv4.tcp_tw_recycle = 1表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。



为了方便描述,我给这个TCP连接的一端起名为Client,给另外一端起名为Server。上图描述的是Client主动关闭的过程,FTP协议中就这样的。如果要描述Server主动关闭的过程,只要交换描述过程中的Server和Client就可以了,HTTP协议就是这样的。

描述过程:
Client调用close()函数,给Server发送FIN,请求关闭连接;Server收到FIN之后给Client返回确认ACK,同时关闭读通道(不清楚就去看一下shutdown和close的差别),也就是说现在不能再从这个连接上读取东西,现在read返回0。此时Server的TCP状态转化为CLOSE_WAIT状态。
Client收到对自己的FIN确认后,关闭 写通道,不再向连接中写入任何数据。
接下来Server调用close()来关闭连接,给Client发送FIN,Client收到后给Server回复ACK确认,同时Client关闭读通道,进入TIME_WAIT状态。
Server接收到Client对自己的FIN的确认ACK,关闭写通道,TCP连接转化为CLOSED,也就是关闭连接。
Client在TIME_WAIT状态下要等待最大数据段生存期的两倍,然后才进入CLOSED状态,TCP协议关闭连接过程彻底结束。

以上就是TCP协议关闭连接的过程,现在说一下TIME_WAIT状态。
从上面可以看到,主动发起关闭连接的操作的一方将达到TIME_WAIT状态,而且这个状态要保持Maximum Segment Lifetime的两倍时间。为什么要这样做而不是直接进入CLOSED状态?

原因有二:
一、保证TCP协议的全双工连接能够可靠关闭
二、保证这次连接的重复数据段从网络中消失

先说第一点,如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

再说第二点,如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。

各种协议都是前人千锤百炼后得到的标准,规范。从细节中都能感受到精巧和严谨。每次深入都有同一个感觉,精妙。

做个快乐的自己。
 
 
http://www.cnblogs.com/Jessy/p/3535612.html

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327039663&siteId=291194637