TCP协议详解二:连接的建立与释放

2023年 7月 10日 61.5k 0

1. 连接建立的“三次握手”

1.1 三次握手流程

TCP协议详解二:连接的建立与释放

  • 客户端发送SYN,表明要向服务器建立连接。同时带上序列号ISN
  • 服务器返回ACK(序号为客户端序列号+1)作为确认。同时发送SYN作为应答(SYN的序列号为服务端唯一的序号)
  • 客户端发送ACK确认收到回复(序列号为服务端序列号+1)

1.2 为什么是三次握手

  • tcp连接是全双工的,数据在两个方向上能同时传递。
  • 所以要确保双方,同时能发数据和收数据
  • 第一次握手:证明了发送方能发数据
  • 第二次握手:ack确保了接收方能收数据,syn确保了接收方能发数据
  • 第三次握手:确保了发送方能收数据
  • 实际上是四个维度的信息交换,不过中间两步合并为一次握手了。
  • 四次握手浪费,两次握手不能保证“双方同时具备收发功能”

2. 连接关闭的“四次挥手”

2.1 为什么是四次挥手

  • 因为tcp连接是全双工的,数据在两个方向上能同时传递。
  • 同时tcp支持半关闭(发送一方结束发送还能接收数据的功能)。
  • 因此每个方向都要单独关闭,且收到关系通知需要发送确认回复

2.2 为什么要支持半关闭

  • 客户端需要通知服务端,它的数据已经传输完毕
  • 同时仍要接收来自服务端的数据
  • 使用半关闭的单连接效率要比使用两个tcp连接更好

2.3 四次握手流程

TCP协议详解二:连接的建立与释放

  • 主动关闭的一方发送FIN,表示要单方面关闭数据的传输
  • 服务端收到FIN后,发送一个ACK作为确认(序列号为收到的序列号+1)
  • 等服务器数据传输完毕,也发送一个FIN标识,表示关闭这个方向的数据传输
  • 客户端回复ACK以确认回复

3. 连接和关闭对应的状态

TCP协议详解二:连接的建立与释放

3.1 状态说明

  • 服务端等待客户端连接时,处于Listen监听状态
  • 客户端主动打开请求,发送SYN时处于SYN_SENT发送状态
  • 客户端收到syn和ack,并回复ack时,处与Established状态等待发送报文
  • 服务端收到ack确认后,也处于Established状态等待发送报文
  • 客户端发送fin后,处于fin_wait_1状态
  • 服务端收到fin并发送ack时,处于close_wait状态
  • 客户端收到ack确认后,处于fin_wait_2状态
  • 服务端发送fin后,处于last_ack状态
  • 客户端收到fin后发送ack,处于time_wait状态
  • 服务端收到ack后,处于closed状态

3.2 time_wait状态

  • 也称为2MSL等待状态,MSL=Maximum Segment LifetIme,报文段最大生存时间,根据不同的tcp实现自行设定。常用值为30s,1min,2min。linux一般为30s。
  • 主动关闭的一方发送最后一个ack所处的状态
  • 这个状态必须维持2MSL等待时间

3.2.1 为什么需要这么做?

  • 设想一个场景,最后这个ack丢失了,接收方没有收到
  • 这时候接收方会重新发送fin给发送方
  • 这个等待时间就是为了防止这种情况发生,让发送方重新发送ack
  • 总结:预留足够的时间给接收端收ack。同时保证,这个连接不会和后续的连接乱套(有些路由器会缓存数据包)

3.2.2 这么做的后果?

  • 在这2MSL等待时间内,该连接(socket,ip+port)将不能被使用
  • 很多时候linux上报too many open files,说端口不够用了,就需要检查一些代码里面是不是创建大量的socket连接,而这些socket连接并不是关闭后就立马释放的
  • 客户端连接服务器的时候,一般不指定客户端的端口。因为客户端关闭然后立马启动,按照理论来说是会提示端口被占用。同样的道理,主动关闭服务器,2MSL时间内立马启动是会报端口被占用的错误
  • 多并发的短连接情况下,会出现大量的Time_wait状态。这两个参数可以解决问题,但是它违背了tcp协议,是有风险的。参数为:tcp_tw_reuse和tcp_tw_recycle
  • 如果是服务端开发,可设置keep-alive,让客户端主动关闭连接解决这个问题

4. 复位报文段

一个报文段从源地址发往目的地址,只要出现错误,都会发出复位的报文段,首部字段的RST是用于“复位”的。这些错误包括以下情况

  • 端口没有在监听
  • 异常中止:通过发送RST而不是fin来中止连接

5. 同时打开

TCP协议详解二:连接的建立与释放

  • 两个应用程序同时执行主动打开,称为“同时打开“
  • 这种情况极少发生
  • 两端同时发送SYN,同时进入SYN_SENT状态
  • 打开一条连接而不是两条
  • 要进行四次报文交换过程,“四次握手”

6. 同时关闭

TCP协议详解二:连接的建立与释放

  • 双方同时执行主动关闭
  • 进行四次报文交换
  • 状态和正常关闭不一样

7. 服务器对于并发请求的处理

  • 正等待连接的一端有一个固定长度的队列(长度叫做“积压值”,大多数情况长度为5)
  • 该队列中的连接为:已经完成了三次握手,但还没有被应用层接收(应用层需要等待最后一个ack收到后才知道这个连接)
  • 应用层接收请求的连接,将从该队列中移除
  • 当新的请求到来时,先判断队列情况来决定是否接收这个连接
  • 积压值的含义:tcp监听的端点已经被tcp接收,但是等待应用层接收的最大值。与系统允许的最大连接数,服务器接收的最大并发数无关

相关文章

如何在 Linux 中使用 logname 命令?
为什么有 HTTPS?HTTPS 如何实现安全通信?
HTTPS的TSL握手流程是什么
华为无线网络射频调优及WLAN跨VLAN的三层漫游示例
502错误是什么、应该怎么排查?
HTTP3为什么抛弃了经典的TCP,而选择QUIC

发布评论