pycrab 阅读(8) 评论(0)

三报文握手

1.概述

TCP是面向连接的协议。TCP建立连接的过程叫做握手,握手需要在客户和服务器之间交换三个TCP报文段,即我们说的“三次握手”(严格讲是一次握手过程中交换了三个报文)。

2.过程

一开始客户端和服务器端中的TCP进程都处于关闭状态,假设客户端主动打开连接,服务器端被动打开连接;这时客户端TCP进程创建传输控制模块TCB,服务器端进程也创建传输控制模块TCB并监听客户请求,以便及时响应。

  • 第一次
    客户端打算建立TCP连接时,向服务器端发送连接请求报文段,其首部中的同步位SYN=1,ACK=0,并选择一个初始序号seq=x,这时客户端TCP进程进入同步已发送状态(SYN-SENT)。
  • 第二次
    服务器端收到连接请求报文段后,如果同意连接,则向客户端发送确认报文段,其首部中的同步位和ACK位都为1,确认号为ack=x+1,并选择一个初始序号为seq=y,这时服务器端TCP进程进入同步已收到状态(SYN-RCVD)。
  • 第三次
    客户端收到服务器端的确认后,还需要向服务器端发送确认报文段,其首部中的同步位和ACK位都为1,确认号为ack=y+1,自己的序号为seq=x+1,这时客户端TCP进程进入已建立连接状态(ESTABLISHED)。

当服务器端收到客户端的确认后,也进入已建立连接状态(ESTABLISHED)。

3.过程图示

4.四报文握手

在三报文握手中的第二次报文发送时,可以先发送一个确认报文段(ACK=1,ack=x+1),再发送一个同步报文段(SYN=1,seq=y),这就变成了四报文握手。

四报文挥手

1.概述

TCP释放连接的过程叫做挥手。挥手需要在客户和服务器之间交换四个TCP报文段。

2.过程

数据传输结束后,通信的双方都可释放连接。假设客户端停止发送数据,先主动关闭TCP连接。

  • 第一次
    客户端TCP进程发送连接释放报文段并进入终止等待1状态(FIN-WAIT-1),其中报文段首部的终止控制位FIN=1,其序号seq=u(u等于已传送过的数据的最后一个字节的序号加1)。
  • 第二次
    服务器端收到连接释放报文段后发出确认报文段并进入关闭等待状态(CLOSE-WAIT),其中报文段首部确认号为ack=u+1,其序号为seq=v(v等同于u)。
    客户端收到服务器端的确认后,进入终止等待2状态(FIN-WAIT-2),等待服务器端发送连接释放报文段。
    这时TCP连接处于半关闭状态,即客户端到服务器端的连接释放了,但是服务器端仍可发送数据,客户端仍可以接收数据。
  • 第三次
    当服务器端停止发送数据,其应用进程会通知TCP释放连接。
    服务器端TCP进程发送连接释放报文段并进入最后确认状态(LAST-ACK),其中报文段首部的终止控制位FIN=1,其序号seq=w(半关闭状态时可能发送了数据),确认号ack=u+1。
  • 第四次
    客户端收到连接释放报文段后发出确认报文段并进入时间等待状态(TIME-WAIT),其中报文段首部的ACK=1,确认号ack=w+1,其序号为seq=u+1。
    此时TCP连接还没有释放,等待时间等待计时器设置的2MSL时间后(建议四分钟),客户端才进入关闭状态。

3.图示

几个问题

  • 1.三报文握手为什么客户端最后还要发送一次确认呢?
    为了防止已失效的连接请求报文段又发给服务器端而产生错误。
    比如客户端发送的第一个请求报文段在某些网络节点滞留了,导致连接释放后的某个时间才到达服务器端,服务器端会向客户端发送确认报文段。
    如果不采用三报文握手,那么新的连接就建立了,但客户端不知道建立了连接,就不会发送数据导致服务器端一直等待;
    而采用三报文握手,客户端不会向服务器端的确认发出确认,服务器端收不到确认,就不会建立连接。
  • 2.为什么四报文挥手客户端在时间等待状态需要等待2MSL?
    其一是为了保证客户端发送的最后一个确认报文段能到达服务器端。因为最后一个ACK报文段可能丢失,服务器端收不到这个报文段会超时重传FIN报文段,在2MSL时间内客户端能收到重传的FIN报文段并重传ACK报文段,保证客户端和服务器端正常关闭TCP连接。
    其二是防止已失效的请求连接报文段出现在本次连接中。客户端在发送完最后一个ACK报文段后经过2MSL时间后,本次连接内的所有报文段将消失,下一次新的连接中就不会有本次的无效的请求连接报文段了。