自学内容网 自学内容网

计网Lesson18 - TCP链接管理



1. TCP 建立连接和释放连接

1.1 三次握手

在这里插入图片描述

  • 为了防止安全问题,TCP 并不是从0开始对包进行编号的,而是随机一个数。
  • 客户端发送SYN包,序列号 = x
    服务器回复SYN-ACK包,序列号 = y,确认号 = x + 1
    客户端回复ACK包,序列号 = x + 1,确认号= y + 1
  • 客户端发送信息时,会先进TCP的缓冲区
    • 这些包已经删去传输层及以前的头了,而应用层往往不带有地址信息
      • TCP会记住头中的信息,在服务器取走包之后,构建一个新TCP头(ACK)发送回发送方。
    • 应用层从接收缓冲区取数据时面临粘包问题:
      • 应用层用协议定义数据边界来区分数据包。
    • 只有在服务器取走包之后TCP才会回消息(ACK包)。
    • 当服务器阻塞时,一直没消息,会触发发送端的超时重传:
      • 但是重传并非无限制,取决于系统设置,一般在5次之后还未成功就发送RST报文,断开连接。
      • TCP中有“重传超时”(Retransmission Timeout,RTO)机制,它规定了客户端等待服务器确认信息的最长时间。如果在这个时间内仍然没有收到确认信息,客户端会停止重传,并可能关闭连接。
    • 服务器阻塞时,会导致发送方一直发消息导致缓存区满了的情况吗?
      • 在TCP通信中,流量控制是通过滑动窗口机制实现的。
      • 如果服务器卡死,那么它将无法处理接收到的数据,也就无法发送ACK,因此窗口不会滑动。这 意味着发送方的窗口会被填满,一旦窗口被填满,发送方就会停止发送数据,直到接收到新的ACK。这就是TCP的流量控制机制如何防止接收方被淹没的。
      • 然而,如果服务器长时间无响应,发送方可能会触发超时重传,这可能会导致网络拥塞。为了解决这个问题,TCP还有一个拥塞控制机制。当检测到网络拥塞时,发送方会减小其发送窗口的大小,减少发送的数据量,以缓解网络拥塞。
    • 如果服务器阻塞,发送方连发两包,因为没有回包,所以确认号不变:
      • 当服务器开始运行时,只回一个ACK包,确认号是第二个包的序号x + length。
      • 如果出现丢包,发送方会根据接收方返回的ACK包确定丢失了哪个包,再进行重传。

1.1.2 三次握手的意义

  • TCP三次握手主要来解决两个重要问题:
    1. 双方确认对方的存在:通过三次握手,客户端和服务器都可以确认对方的存在,即对方的 IP 地址和端口号是正确的,可以接收到数据。
    2. 双方确认对方已准备好接收数据:三次握手过程中,双方都会发送一个 SYN 包,表明自己已经准备好了,可以发送数据,也可以接收数据。
  • 为什么是三次握手而不是两次握手?前两次握手已经可以确立连接了:
    • 三次握手的过程:
      1. SYN:客户端发送一个 SYN 包给服务器,请求建立连接。这个 SYN 包包含一个随机的序列号 A。
      2. SYN-ACK:服务器收到 SYN 包后,会确认客户端的 SYN(ACK=A+1),同时发送自己的 SYN 包,这个 SYN 包包含一个随机的序列号 B。
      3. ACK:客户端收到服务器的 SYN-ACK 包后,会确认服务器的 SYN(ACK=B+1)。至此,连接建立成功。
    • 在这个过程中,第三次握手(ACK)的目的是为了确认自己收到了对方的 SYN 包,也就是说,确认对方已经准备好了。如果没有这一步,那么服务器可能会一直等待确认,因为它不知道客户端是否已经收到了自己的 SYN 包。

在这里插入图片描述

  • 如果只有两次握手
    • 客户端的首个连接请求一直没送到,触发超时重传。
    • 客户端跟服务器连接后关闭,此时第一个SYN包才到,服务器会回一个SYN包。
    • 如果是两次握手,会导致这个关闭的客户端一直占用服务器资源,造成资源浪费。

1.2 四次挥手

在这里插入图片描述

  • 第一次挥手
    • 序号seq字段的值设置为u,它等于TCP客户进程之前已经传送过的数据的最后⼀个字节的序号加1。
    • TCP规定终止标志位FIN等于1的TCP报文段即使不携带数据,也要消耗掉⼀个序号。
    • 确认号ack字段的值设置为v,它等于TCP客户进程之前已收到的数据的最后⼀个字节的序号加1。
  • 第⼆次挥手
    • 序号seq字段的值设置为v,它等于TCP服务器进程之前已传送过的数据的最后⼀个字节的序号加1。这也与之前收到的TCP连接释放报文段中的确认号v匹配。
    • 确认号ack字段的值设置为u+1,这是对TCP连接释放报文段的确认。

  两次挥手之后,从TCP客户进程到TCP服务器进程这个方向的连接就释放了,但TCP服务器进程如果还有数据要发送,TCP客户进程仍要接收,也就是从TCP服务器进程到TCP客户进程这个方向的连接并未关闭。
  无论是客户端还是服务器,都可以主动发起关闭连接的请求。这是 TCP 协议的一个重要特性,它确保了连接的双向性和全双工通信。

  • 第三次挥⼿
    • TCP连接释放报文段首部中的终止标志位FIN和确认标志位ACK的值都被设置为1。表明这是⼀个TCP连接释放报文段,同时也对之前收到的TCP报文段进行确认。
    • 序号seq字段的值假定被设置为w,这是因为在半关闭状态下TCP服务器进程可能又发送了⼀些数据。
    • 确认号ack字段的值被设置为u+1,这是对之前收到的TCP连接释放报文段的重复确认。
    • TCP服务器进入LAST-ACK状态。
  • 第四次挥⼿
    • 序号seq字段的值设置为u+1,这是因为TCP客户进程之前发送的TCP连接释放报⽂段虽然不携带数据,但要消耗掉⼀个序号。
    • 确认号ack字段的值设置为w+1,这是对所收到的TCP连接释放报文段的确认。
    • TCP客户端进⼊TIME-WAIT状态,等待2MLS,MSL是最长报文段寿命(Maximum Segment Lifetime) 的英文缩写词,[RFC793]建议为2分钟。也就是说,TCP客户进程进入时间等待(TIME-WAIT)状态后,还要经过4分钟才能进入关闭(CLOSED)状态。

面试题:

  1. 如果遇到大量CLOSE_WAIT情况是什么原因,怎么解决?

    • 遇到大量CLOSE_WAIT,证明应用程序没有处理完发送来的数据,所以迟迟没有发送第三次挥手的FIN包,这主要是程序出了问题。
    • 解决办法有:
      • 检查服务端程序:首先需要检查服务端的程序,看是否在接收到客户端的关闭请求后,正确地关闭了连接和释放了相关资源。
      • 优化代码:如果服务端程序在处理请求时出现异常,那么需要优化代码,确保即使在出现异常的情况下,也能正确地关闭连接和释放资源。
      • 设置超时:可以在服务端设置超时,如果在一定时间内没有接收到客户端的数据,那么就自动关闭连接。这样可以避免因为客户端异常关闭(例如崩溃或者网络问题),导致服务端一直等待的问题。
      • 使用心跳:另外一种方法是使用心跳机制,定期检查客户端是否还在。如果在一定时间内没有收到客户端的心跳,那么就认为客户端已经关闭,然后服务端就可以关闭连接。
  2. 如果遇到大量TIMe_WAIT状态是什么原因,该如何解决?

    • 遇到大量TIME_WAIT主要原因:
      • 大量的短连接存在:特别是在 HTTP 请求中,如果 connection 头部取值被设置为 close 时,基本都由服务端发起主动关闭连接。
      • TCP 四次挥手关闭连接机制:为了保证 ACK 重发和丢弃延迟数据,设置 time_wait 为 2 倍的 MSL(报文最大存活时间)。
    • 解决办法:
      • 客户端层面:在客户端将 HTTP 请求头里 connection 的值设置为 keep-alive,将短连接改成长连接。
      • 服务器层面:可以通过修改服务器的系统内核参数来进行优化1。例如,允许将 TIME_WAIT 状态的 socket 重新用于新的 TCP 连接,或者缩减 MSL 值。
    • 其实出现大量TIME_WAIT属于正常现象。TIME_WAIT是传输层的规定,程序员无法操作,而且TIME_WAIT对资源占用不大,所以不太需要处理。

原文地址:https://blog.csdn.net/2301_78981471/article/details/136333440

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!