🔌 第二章 用电信号传输TCP/IP数据
📄 一句话概括

close 后套接字不立刻消失——先半关闭、再等几十秒防【迟到的旧包】闯进新连接,然后控制信息才交还内存。

📝 本节和前面几节的关系

FIN 挥完手;本篇看资源何时真正回收。

一、等待期的作用

同样的 IP+端口立刻重开新连接, 旧连接在网络里迷路的包可能闯进来冒充—— 等一段时间让它们自然死亡(超时),才彻底删除记录。

二、对端可能还没收完

本端 close 后仍要接收对端最后的数据—— 半关闭状态就是为此留的缓冲。

三、动手 Demo:删除套接字

close 之后的三个阶段:

for a, b, c in [('close() 返回','半关闭','对方可能还在发'),
               ('收到 ACK','等待','防迷路包乱入'),
               ('超时几十秒','删除','控制信息交还内存')]:
    print('%-10s %-6s %s' % (a, b, c))

实跑输出:

--------------------------------------------------------------------
删除套接字
--------------------------------------------------------------------
  close 之后套接字不是立刻消失:

  阶段               状态         为什么
  -------------------------------------------------
  close() 返回       半关闭       对方可能还在发
  收到对方 ACK       等待         防迷路包乱入
  超时(几十秒)     彻底删除     控制信息交还内存
  -------------------------------------------------

  等待期是防【旧连接的迟到大包】闯进新连接——
  同样的 IP+端口马上重开会撞包。

Linux 上这个状态叫 TIME_WAIT,时长约 2MSL—— 高并发短连接服务器会在这里堆积大量端口。

30 秒实验

  1. 高频开关连接后用 netstat 数 TIME_WAIT 数量。
  2. 想想为什么客户端端口比服务器端口更容易耗尽。
  3. 查一下 SO_REUSEADDR 解决什么问题。

常见误区

  1. 以为 close 即释放——还有几十秒等待期。
  2. 以为等待期是浪费——它防旧包冒充新连接。
自测三问(点开对答案) 1. close 后套接字立刻删除吗? —— 否,有等待期。 2. 等待期防什么? —— 旧连接迟到的包闯进新连接。 3. 半关闭期间还能收数据吗? —— 能,对端可能还没发完。

相关笔记