朝三慕四

 

 

 

 

 

 

 

 

 

 

  • 最初两端的TCP进程都处于CLOSE(关闭)状态。
    上图中A主动打开连接,B被动打开连接。
  • B打开连接后处于LISTEN(监听状态),等待客户的连接请求。
  • A向B发送请求报文,SYN=1,ACK=0,选择一个初始序号seq=x。
  • B 收到连接请求报文,如果同意建立连接,则向 A 发送连接确认报文,SYN=1,ACK=1,确认号为ack= x+1,同时也选择一个初始的序号 seq=y。
  • A 收到 B 的连接确认报文后,还要向 B 发出确认,确认号为ack= y+1,序号为 seq=x+1。
  • B 收到 A 的确认后,连接建立。

TCP的三次握手事情就是这么个事情。(如有错误,还望指正)下面来看看TCP的四次挥手

 

 

 

以下描述不讨论序号和确认号,因为序号和确认号的规则比较简单。并且不讨论 ACK,因为 ACK 在连接建立之后都为 1。

  • A 发送连接释放报文,FIN=1。
  • B 收到之后发出确认,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向 B 发送数据。
  • 当 B 不再需要连接时,发送连接释放报文,FIN=1。
  • A 收到后发出确认,进入 TIME-WAIT 状态,等待 2 MSL(最大报文存活时间)后释放连接。
  • B 收到 A 的确认后释放连接。

 

四次挥手的原因

CLOSE-WAIT

客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。

TIME-WAIT

客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。

为什么A在TIME-WAIT状态必须等待2MSL的时间呢?

这么做有两个理由:

  • 为了保证A发送的最后一个ACK报文段能够到达B。
    A发送的这个ACK报文段有可能丢失,如果 B 没收到 A 发送来的确认报文,那么A就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
  • 防止“已经失效的连接请求报文段”出现在本链接中。
    A在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接的时间内所产生的所有报文段都从网络中消失。这样下一个新的连接中就不会出现这种旧的连接请求报文段。

 

为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

posted @ 2019-10-09 17:47  FromScratch  阅读(149)  评论(0编辑  收藏  举报