三次握手 && 四次挥手

1,三次挥手

     第一次握手:

                             建立连接时,客户端向服务器发送一个 请求包,在这个包中,SYN=1,ACK=0,表示这是一个请求连接的报文,

                             系统为这个报文随机产生一个序列号 x,并且客户端进入SYN_SENT状态,等待服务器的确认。

                              

     第二次握手:

                                服务器收到连接请求后,必须发送一个 ACK 确认包,同时自己也要发送一个请求包 ,就是 SYN+ACK

                                在ACK确认包中,ACK=1,SYN=1,说明这是一个TCP连接数据响应报文,

                                还包含者系统为服务端的这个报文随机产生的序列号 y。

                                以及服务器对客户端初始序列号的确认号=(客户端的序列号+1)=x+1。

                                此时服务器进入SYN_RECV状态,

      第三次握手:

                             客户端收到SYN+ACK包,向服务器发送 序列号=x+1,确认号=y+1 的ACK数据包。

                             此包发送完毕,客户端和服务器进入ESTABLISHED状态,三次握手完成。

     对应代码:

                           connect 函数,一旦调用connect函数,内核就会给对端发送SYN请求,

                           对方的网卡收到SYN请求,将请求交给网络驱动程序,驱动程序交给操作系统内核,内核交给TCP相关模块。

                           TCP模块收到SYN后,向请求方发送ACK+SYN。

                           请求方的网卡收到ACK+SYN后,交给TCP模块,给对方发送ACK.

                           到这里,三次握手就完成了,然后connect函数 才返回。

                           对方的accept函数结束阻塞,并且返回一个新的文件描述符。

                           三次握手和代码并没有什么关系,是调用connect函数触发触发内核的相关操作完成的。

      问题:为什么是三次握手,两次握手行不行?

                          答; 在两次握手情况下,客户端向服务器发送连接请求,服务器确认应答,连接就建立了。

                                考虑下面的情况,第一次连接请求被阻塞到网络的某个地方,然后触发超时重传,

                               发送一个新的连接请求,并成功连接和释放。这时被阻塞的连接请求被服务器收到,

                              一个新的连接就建立了,服务器一直尝试从客户端读取数据,但是始终没有,服务器的资源被浪费 。

                            在三次握手的情况下,即使发生 上述情况,也需要服务器请客户端发送请求去确认连接,

                            这时客户端不会给服务器发送确认消息,因为自己没有要请求连接,连接就无法完成。

                                

          

2,四次挥手:

      第一次挥手:

                                 首先客户端向服务器发送一个FIN数据包,这个包中包含  FIN=1 ,

                                 序列号=u(等于前面已经发送的数据最后一个字节序列号+1)。

                                 客户端进入FIN_WAIT_1状态,主动断开与服务器的链接。

      第二次挥手 :

                           服务器收到FIN数据包,发送ACK数据包 ,ACK=1 ,序列号=w,确认序号=u+1。

                           服务器进入CLOSE_WAIT 状态。

                           (如果服务器出现大量的CLOSE_WAIT状态,那肯定是服务器没有关闭文件描述符

                           此时,客户端到服务器的连接断开了,但是服务器到客户端的连接没有断开,服务器可以向客户端发数据。

      第三次挥手:

                          客户端收到ACK报文,进入FIN_WAIT_2状态,等待服务器发送连接释放的报文。

                          服务器向客户端发送FIN数据包,FIN=1,确认号还是=u+1,由于是半连接,服务器可能还 发数据了,

                          所以序列号暂定 =v,此时服务器进入LAST_ACK,状态,等待客户端的确认报文。

       第四次挥手:

                         客户端收到 FIN 数据包 ,发出确认数据包  ACK=1,确认号=v+1,序列号=u+1 。

                       (ACK数据包不携带数据不消耗序号,所以序列号还是 u+1)

                         进入TIME_WAIT状态,在经过2*MSL时间后进入CLOSE状态。

                         等待2*MSL的原因是,能保证收到因为最后一个ACK确认包丢包引起对方超时重传一个新的FIN包。

                         (MSL表示一个数据报从的发送到接受所经历的最大时间,所以TIME_WAIT =2*MSL)

                         服务器在收到确认报文后直接进入CLOSE 状态。进入CLOSE状态就是完全断开连接了。   

        对应代码:

                     客户端调用 close()函数,触发TCP模块相关操作为对方发送一个FIN请求,对方收到请求后

                     由TCP模块发送一个ACK应答,这个过程对应着第一,二次挥手。

                     和代码并没有什么关系,是调用close()函数触发内核的相关操作完成的。

                     然后对方再尝试去读,就会知道没有数据要发了,就会调用close()函数触发TCP模块相关操作为客户端发送

                    一个FIN请求,客户端收到请求 后,由TCP模块发送一个ACK应答,这个过程对应着第三 ,四次挥手。

                    和代码并没有什么关系,是调用close()函数触发内核的相关操作完成的。

                这也是为什么第二和第三次挥手,不能一块完成的原因,因为这两次挥手,不再同一 时间段。是两个不同的函数触发的。

  问题:为什么是四次挥手,三次挥手行不行?

            答:第一二次挥手仅表示客户端没有数据要发送了,但是服务器不一定就没有数据发送了,所以服务器对应的

                   第三四次挥手,必须独立的存在以保证半连接状态。

                          

猜你喜欢

转载自blog.csdn.net/wm12345645/article/details/81838515