TCP的三次握手与四次挥手
TCP通信过程包括三个步骤:建立TCP连接通道,传输数据,断开TCP连接通道。
1.连接建立(TCP三次握手)
TCP建立连接为什么是三次握手,而不是两次或四次?
这是一个我个人比较喜欢的例子,比如打电话时我们对话如下:
如图可以看出,通俗的来讲,如果是两次握手,接收方是无法确定发送方是否可以接收到自己的消息(下面会给出TCP两次握手的描述)
2.TCP 通信流程
先描述一下各个字段的作用:
(1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
(2)确认序号:Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。
(3)SYN(标志位):发起一个新连接。 (4)ACK(标志位):确认序号有效。
TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答SYN+ACK ,并最终对对方的 SYN 执行 ACK 确认。
TCP三次握手的过程如下:
(1)客户端发送SYN(Seq=x)报文给服务器端,进入SYN_SEND状态。
(2)服务器端收到SYN报文,回应一个SYN (Seq=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
(3)客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。
3、下面用实例讲下wireshark中的tcp三次握手过程:
1)打开wireshark后,在浏览器输入访问地址:http://14.215.177.38/(百度的ip),wireshark自动捕获数据包,然后过滤自己需要分析的数据,这里是过滤与主机通信的记录,
使用抓包工具可以看出TCP链接的详细过程,在我们像百度发起访问的时候,本机55752端口向百度的80端口发起请求,下文以客户端和服务端作为称呼
第一帧:客户端发送一个标志位[SYN],代表建立连接,并发送Seq=0(起始序号)
第二帧:服务端回复一个确认包,标志位[SYN,ACK],代表确认序号有效,回复Seq=0(服务器的序号),Ack=1(表示客户端Seq序号被确认=Seq+1)
第三帧:客户端回复一个确认包,标志位[ACK],回复Seq=1(自身的序号),Ack=1(表示服务端Seq序号被确认=Seq+1)
结论:通过实例抓包工具可以看出,只有两次握手的话
- 如果只是两次握手,至多只有连接发起方的起始序列号能被确认,另一方选择的序列号则得不到确认
- 为了实现可靠数据传输,TCP 协议的通信双方,都必须维护一个序列号,以标识发送出去的数据包中,哪些是已经被对方收到的。三次握手的过程即是通信双方相互告知序列号起始值,并确认对方已经收到了序列号起始值的必经步骤
- 防止失效的连接请求报文段被服务端接收,从而产生错误。
连接终止(TCP四次挥手)
建立一个连接需要三次握手,而终止一个连接要经过四次握手,这是由TCP的半关闭(half-close)造成的。具体过程如下图所示(图片来源百度)
TCP连接的终止
1:客服端调用close等函数主动关闭, 并向服务端发送一个含FIN的报文, 然后就进入FIN-WAIT1阶段, 该阶段是等待对端的ACK到来.
2:服务端接收到客户端的FIN后, 立马向客户端回一个ACK确认, 然后进入CLOSE-WAIT阶段, 该阶段服务端还能够将没有发送完的数据发送给对端. 当服务端将数据发送完后再发送一个FIN段, 之后进入 LAST-ACK阶段, 等待客服端的ACK到来
3:当客户端接收到对端的ACK时, 进入FIN-WAIT2阶段, 该阶段客服端还能够继续接收数据, 但是不能在发送数据了;
当接收到服务端端的FIN后立马向服务端端发送ACK确认, 之后进入TIME_WAIT阶段. 等待2MSL后客户端彻底关闭.
4:服务端收到ACK后就完全将关闭该连接.
注意
主动关闭的一端在挥手过程中还能够接收数据, 只是不能够在发送数据了.:
最后是被动关闭端先关闭连接, 之后主动关闭端才会被关闭.
使用实例讲下wireshark中的tcp四次挥手过程:
第一帧:客户端发送一个标志位[FIN],代表释放连接,并发送Seq=443(起始序号)
第二帧:服务端回复一个表示收到客户端释放链接的请求,但由于可能存在还未发完的数据,服务端先不关闭链接
标志位[ACK],代表确认序号有效,回复Seq=40012(服务器的序号),Ack=444(表示客户端Seq序号被确认=Seq+1)
第三帧:服务端再发完数据后回复一个确认包(代表可与关闭链接),标志位[ACK],回复Seq=40012(自身的序号),Ack=444(表示服务端Seq序号被确认=Seq+1)
第四帧:客户端收到服务器的释放链接数据包,发送一个标志位[ACK],Seq=444,Ack=40013,表示可以释放链接,客户端在等待2MSL时间后断开链接
那么问题来了:(问题来源于)https://blog.csdn.net/scuzoutao/article/details/81774100
1,为什么要四次挥手
答:前两次挥手是为了断开client至server的连接,后两次挥手是为了断开server至client的连接,如果没有第四次挥手,会出现如下状况:
server发送FIN数据包并携带ACK至client之后直接断开连接,如果client没有收到这个FIN数据包,那么client会一直处于等待关闭状态,这是为了确保TCP协议是面向连接安全有保证锝。
上面解释了为什么不是三次挥手,同理,两次挥手也是不安全的。不能保证server与client都能正确关闭连接释放资源,而不会造成资源浪费。
2,四次挥手之后client为什么还要等待2MSL的时间才释放资源关闭连接?
答:如果client第四次挥手的确认报文段没有被server接收,那么server便会重发第三次挥手的FIN报文段,因此client要停留2MSL的时长来处理可能会重复收到的报文段。让之前建立的client-server通信过程中或者是挥手过程中由于网络不通畅产生的滞留报文段失效。如果不等待2MSL,那么建立新连接之后,可能会收到上一次连接的旧报文段,可能会造成混乱。
Tcp图中有字段介绍:
(1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
(2)确认序号:Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。
(3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:
(A)URG:紧急指针(urgent pointer)有效。
(B)ACK:确认序号有效。
(C)PSH:接收方应该尽快将这个报文交给应用层。
(D)RST:重置连接。
(E)SYN:发起一个新连接。
(F)FIN:释放一个连接。