盗来一张图:
以客户端主动发起请求为例,来看三次握手是怎么形成的:
1.第一次握手: 客户端主动发起请求,向服务器发送SYN =1 ,seq = x;这两个代表啥意思呢?SYN 是一个标识符,表示请求建立新连接。等于1的时候有效,一般都是等于1。因为要发起连接啊。seq = x;代表发送的数据(可以理解为一段测试信息),x代表的就是个假设的值 x。
2. 第二次握手:服务端收到请求,SYN = 1;ACK =1;ack = x+1;seq= y;这几个代表什么意思?SYN =1;还是请求建立新连接。ACK =1 ,ACK也是个标识符,仅当等于1 的时候有效,ACK =1 ;表示客户端你发的请求我收到了,ack = x +1;告诉客户端我收到的是 x+1 ,那么说明是正确的。对,服务端收到的ack 就是客户端发送的x 再加个 1。同理,服务端发送的seq = y,客户端返回给服务端的时候,ack会变成 y +1 ; 反正就是在发送的seq基础上加1 了。后面解释为什么加1。
3. 第三次握手:ACK = 1;ack = y+1;seq = x+1; 第三次的时候就没有发SYN = 1 了,这是因为,双方已经都发送过,说明已经同意建议连接了,就好比打电话,你打过去,对方接听了。ACK = 1;还是告诉对方,我收到了。ack = y+1;告知对方,我收到的是y+1;看吧,发送过来的是y, 那么ack就是加1;
然后,客服端和服务端都进入 ESTABLISHED。
问题:那么为什么要进行三次握手呢?两次不行吗?
为了防止无效的请求占有服务端资源,或者突然失效的请求又发送给服务端,导致发生错误。
(1)假设只有两次握手,客户端发送请求,服务端收到后直接为客户端开启一个服务端口。
如果,因为网络i原因或者其他原因,服务端第二次握手发送的数据,客户端 没有收到。那么客户端,就会再次发送请求,建立连接,服务器收到后又开启一个端口。这样就导致了资源浪费。
如果是三次握手,就不会出现这情况。三次握手情况下,第二次握手服务端发的数据,没有收到客户端的应答,那么服务器端则知道客户端没有收到请求,就不会开启端口。
(2)已经失效的客户端请求,由于某种原因传给了服务端,服务端没有发出第三次握手的确认,就为客户端开启了端口,并响应请求就会导致一些错误发生。
太棒了!下面看四次挥手是怎么样的?
自己画的草图:
哈哈啊哈,凑合看看吧。以客户端发起断开请求为例:
第一次挥手: 客户端发送FIN =1;seq= u; FIN 表示请求断开一个连接,seq还是我们之前说的是个测试连接的信息段。
第二次挥手: 服务端收到客户端的断开连接请求,发送ACK =1;ack = u+1;seq = v;告诉客户端,你的断开请求我收到了。
此时,客户端已经知道服务端收到了断开连接请求,但是服务端没有发送FIN,可能还有数据没有发送完。
第三次挥手:客户端发送FIN = 1;ACK =1;seq = w; ack = u +1;这时候服务器已经发送完全部数据,发送FIN 告诉客户端,可以断开连接了。
第四次挥手: ACK =1 ;ack= w+1;seq= u+1; 这时候客户端告诉服务端我收到你的断开连接的请求了,可以断开了。
至此,服务端断开了 连接,进入关闭状态。客户端等待2MSL关闭连接。
问题:那么为什么握手三次呢?挥手却要四次?
答: 三次握手建立连接是因为,第二次握手,服务器的请求建立连接SYN 和 确认收到客户端请求ACK 是一起发送的。
因为客户端发送请求连接的时候,服务端可以直接确认收到请求,并同时发起请求。但是挥手的时候不行,因为不能说断开就断开,客户端手里活儿忙完了,服务端还没忙完呢,所以确认收到客户的断开连接,和服务端自己请求断开连接是分开发的,因此多了一次挥手。
问题:为什么客户端要等待2msl才关闭连接?
因为客户最后发送的ACK报文,服务端不一定能收到。所以要等等,服务端发送完FIN报文后,在1MSL时间内,如果没有收到客户端的ACK,那么会再次发送FIN报文。客户端就在等,看看会不会服务端再发FIN ,再次发送说明没收到,那么客户端再次发送ACK报文。如果2MSL时间内,都没有服务端的FIN ,说明服务端收到了。那么客户端也可以关闭连接了。
好了。如果有问题,欢迎评论区指正。
补充:为啥加1
The server responds to the client with a sequence number of zero,
as this is its first packet in this TCP session,
and a relative acknowledgement number of 1.
The acknowledgement number is set to 1 to indicate the receipt of the client's SYN flag in packet
Notice that the acknowledgement number has been increased by 1 although no payload data has yet been sent by the client.
This is because the presence of the SYN or FIN flag in a received packet triggers an increase of 1 in the sequence.
(This does not interfere with the accounting of payload data, because packets with the SYN or FIN flag set do not carry a payload.)
服务器以0的顺序号响应客户端,因为它是此TCP会话中的第一个数据包,并且相对确认号为1。确认号设置为1以指示在数据包中接收到客户端的SYN标志。请注意,尽管客户端尚未发送任何有效载荷数据,但确认号已增加1。 这是因为在接收到的数据包中SYN或FIN标志的存在会触发序列增加1。 (这不会影响有效载荷数据的记帐,因为设置了SYN或FIN标志的数据包不携带有效载荷。)
说白了就是,回复的这个+1,是代表他收到了SYN标识 。