TCP连接管理


三次握手具体流程

  1. 客户端发送一个SYN报文,SYN=1,随机生成一个序列号client_isn放入序列号字段.
  2. 服务端接收SYN报文后,向客户端发送一个SYN-ACK报文,SYN=1,ack=client_isn+1放入ACK字段,随机生成一个序列号server_isn放入序列号字段.
  3. 客户端接收服务端的SYN-ACK报文后,向服务端发送一个ACK报文,SYN=0,ack=server_isn+1

img

为什么需要三次握手,而不是两次握手

TCP是全双工通信,客户端和服务端都需要根据对方的序列号来记录数据的接收情况,所以在建立连接时需要互相告知起始序列号.本来的通信过程是这样的:

  1. A->B SYN
  2. B->A ACK
  3. B->A SYN
  4. A->B ACK

由于第2步和第3步都是B发送给A,并且TCP报文头部允许SYN和ACK的共存,所以可以把这两步合成一步,最终形成了三次握手.

四次挥手流程

  1. 当客户端没有数据可以发送,客户端发送一个FIN报文给服务端,然后进入FIN_WAIT_1状态
  2. 服务端接收FIN报文,进入CLOSE_WAIT状态,并返回一个ACK消息给客户端,当客户端接收到ACK,进入FIN_WAIT2状态
  3. 当服务端没有数据可以发送,服务端发送一个FIN报文给客户端
  4. 客户端接收FIN报文,然后发送一个ACK消息给服务器并进入TIME_WAIT状态,服务器接收到ACK消息后进入CLOSED状态.
  5. 客户端等待2个最大段存活时间后,进入CLOSED状态

img

四次挥手中timewait的作用

  • TCP使用序列号来唯一的标识数据.如果一个服务器向客户端传递数据,但客户端还没有收到数据.但此时连接关闭了.如果有另外一个新的连接使用同样源地址,源端口号和目标地址,目标端口号连接上服务器,并且收到了上次那个服务器返回的数据,但其实这个数据是无效的,那么就会可能导致客户端获取到错误的数据.使用timewait,那么收到这个错误的数据时,这个数据已经至少经历了2个最大段存活时间(Max Segment Lifetime),那么认为这个数据是无效的,进而丢弃这个消息,最终保证了数据传输的正确性..
  • 客户端如果返回给服务器的ACK丢失了,那么服务器会认为当前连接还没有正常关闭.如果有另外一个连接使用了同样源地址,源端口号和目标地址,目标端口号和服务器进行三次握手,由于服务端认为连接没有结束,就会返回RST响应,进而握手过程结束.通过使用timewait可以等待服务端重新发送FIN,然后再重新进行ACK.

参考资料


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!