-
三次握手🤝
(1)概要:
第一次握手是在建立连接,客户端发送连接请求报文段,把标有
SYN
的数据包发给服务器端即为接收端。第二次握手是服务器端即接收端收到客户端的
SYN
的报文段,同时发送标有SYN/ACK
的数据包。第三次握手是客户端收到服务器端的
SYN/ACK
的数据包后,向服务器端发送标有ACK
的数据包。
(2)详情:
握手过程中使用了
TCP
的标志,SYN
和ACK
。初始化状态:客户端处于
close
关闭状态,服务器处于Listen
监听状态。第一次握手:客户端发送请求报文将
SYN=1
同步序列号和初始化seq=x
发送给服务端,服务端从初始化状态,创建连接,等待客户端,确认接收后的状态为SYN_Receive
。这个时候客户端处于等待状态为SYN_Send
。第二次握手,服务器接收到报文后(
SYN=1,seq=x
)收到请求后请求报文变为同步序列号SYN=1
,初始化序列号seq=1
,确认号ACK=1,ack=x+1
,服务器为SYN_Receive
状态,发送端的状态为:SYN_Send
。第三次握手,客户端收到服务端的数据包(收到响应后),然后发送同步序列号
ack=y+1
和数据包的序列号seq=x+1
和ACK=1
确认包作为应答(第三次握手:ACK=1,seq=x+1,ack=y+1
),客户端和服务端变化为established
状态。
- TCP连接为什么是三次握手而不是二次?
假如现在客户端想向服务端进行握手,它发送了第一个连接的请求报文,但是由于网络信号差或者服务器负载过多,这个请求没有立即到达服务端,而是在某个网络节点中长时间的滞留了,以至于滞留到客户端连接释放以后的某个时间点才到达服务端,那么这就是一个失效的报文,但是服务端接收到这个失效的请求报文后,就误认为客户端又发了一次连接请求,服务端就会想向客户端发出确认的报文,表示同意建立连接。
假如不采用三次握手,那么只要服务端发出确认,表示新的建立就连接了。但是现在客户端并没有发出建立连接的请求,其实这个请求是失效的请求,一切都是服务端在自相情愿,因此客户端是不会理睬服务端的确认信息,也不会向服务端发送确认的请求,但是服务器却认为新的连接已经建立起来了,并一直等待客户端发来数据,这样的情况下,服务端的很多资源就没白白浪费掉了。
采用三次握手的办法就是为了防止上述这种情况的发生,比如就在刚才的情况下,客户端不会向服务端发出确认的请求,服务端会因为收不到确认的报文,就知道客户端并没有要建立连接,那么服务端也就不会去建立连接,这就是三次握手的作用。
-
四次握手👋
当客户端和服务端通过三次握手建立了
TCP
连接以后,当数据传送完毕,断开连接就需要进行TCP
的四次挥手。
第一次挥手,客户端设置
seq
和ACK
,向服务器发送一个FIN=1
报文段。此时,(第一次挥手,FIN=1,seq=u
)客户端进入FIN_WAIT
状态,表示客户端没有数据要发送给服务端了。第二次挥手,服务端收到了客户端发送的
FIN
报文段,向客户端回了一个ACK
报文段。第三次挥手,服务端向客户端发送
FIN
报文段,请求关闭连接,同时服务端进入LAST_ACK
状态。第四次挥手,客户端收到服务端发送的
FIN
报文段后,向服务端发送ACK
报文段,然后客户端进入TIME_WAIT
状态。服务端收到客户端的ACK
报文段以后,就关闭连接。此时,客户端等待2MSL
(指一个片段在网络中最大的存活时间)后依然没有收到回复,则说明服务端已经正常关闭,这样客户端就可以关闭连接了。
- TCP连接为什么是四次挥手而不是三次?
TCP
协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP
是全双工 模式,这就意味着,在客户端想要断开连接时,客户端向服务端发送FIN
报文,只是表示客户端已经没有数据要发送了,但是这个时候客户端还是可以接收来自服务端的数据。当服务端接收到
FIN
报文,并返回ACK
报文,表示服务端已经知道了客户端要断开连接,客户端已经没有数据要发送了,但是这个时候服务端可能依然有数据要传输给客户端。当服务端的数据传输完之后,服务端会发送
FIN
报文给客户端,表示服务端也没有数据要传输了,服务端同意关闭连接,之后,客户端收到FIN
报文,立即发送给客户端一个ACK
报文,确定关闭连接。在之后,客户端和服务端彼此就愉快的断开了这次的TCP
连接。或许会有疑问,为什么服务端的
ACK
报文和FIN
报文都是分开发送的,但是在三次握手的时候却是ACK
报文和SYN
报文是一起发送的,因为在三次握手的过程中,当服务端收到客户端的SYN
连接请求报文后,可以直接发送SYN+ACK
报文。其中ACK
报文是用来应答的,SYN
报文是用来同步的。但是在关闭连接时,当服务端接收到FIN
报文时,很可能并不会立即关闭SOCKET
,所以只能先回复一个ACK
报文,告诉客户端,你发的FIN
报文我收到了,只有等到服务端所有的数据都发送完了,才能发送FIN
报文,因此ACK
报文和FIN
报文不能一起发送。所以断开连接的时候才需要四次挥手来完成。
-
检验
用Wireshark
抓包可以检验tcp连接:
网友评论