首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >计算机网络-CLOSE_WAIT详解

计算机网络-CLOSE_WAIT详解

作者头像
运维小路
发布2026-04-02 13:21:30
发布2026-04-02 13:21:30
1370
举报
文章被收录于专栏:运维小路运维小路

作者介绍:简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。

目前几乎所有的应用都会跟网络打交道,所以我们了解和熟悉网络对我们后续的排错是很有必要的,我这里讲解的部分主要是我个人理解来进行讲解。

前面我们介绍 TCP 的 4 次挥手,在被动关闭方里面有一个状态就是 CLOSE_WAIT,今天我们结合实际情况来讲解如果它多了以后会发生什么事情。

但是讲解他之前我们还需要重点介绍一下5元组,因为我们的CLOSE_WAIT状态实际和这个5元组强相关。

源 IP 地址(Source IP):发送方主机地址

源端口(Source Port):发送方应用端口(0~65535)

目的 IP 地址(Destination IP):接收方主机地址

目的端口(Destination Port):接收方服务端口

传输层协议(Protocol):TCP(6)、UDP(17)、ICMP 等

示例:

代码语言:javascript
复制
192.168.1.100:54321 → 123.45.67.89:80 (TCP)

从上面我们看到了一个54321端口,这个端口是应用发起方从内核里面随机选的一个,但是这个随机的范围从哪里来的呢?这个也是大部分发行版默认的限制。

代码语言:javascript
复制
[root@localhost ~]# cat /proc/sys/net/ipv4/ip_local_port_range
32768	60999

所以当业务很繁忙的时候就会出现问题

端口耗尽问题:对于主动发起连接的客户端,每个连接都占用一个本地端口。TIME_WAIT期间端口无法被复用。在Linux系统中,本地端口的范围通常是32768-61000,约28232个端口。如果每秒建立大量短连接,很快就会耗尽可用端口。

连接建立延迟:某些情况下,即使端口没有完全耗尽,频繁的TIME_WAIT也会导致连接建立变慢。因为内核需要检查端口是否可用,增加了额外的开销。

资源占用:每个TIME_WAIT连接会占用约0.5KB的内核内存,虽然比CLOSE_WAIT少很多,但数十万个TIME_WAIT连接仍然会占用可观的内存资源。

注意:这里的端口耗尽只有源 IP、目标 IP、目标端口都相同时,才会受单个端口的限制。

下面我涉及一个程序来模拟这个问题,这个是在python2.7下模拟成功,服务端和客户端都在本机。

代码语言:javascript
复制
# -*- coding: utf-8 -*-
import socket
import time
import errno

PORT = 8888

# 先启动服务端(非线程,直接启动)
server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', PORT))
server.listen(1000)

# 服务端 accept 会阻塞,所以客户端必须放子进程
# 这里用最简单方案:fork 分裂出服务端 + 客户端

import os
pid = os.fork()

if pid == 0:
    # 子进程:服务端
    while 1:
        try:
            c, addr = server.accept()
            c.close()
        except:
            break
else:
    # 父进程:客户端
    time.sleep(1)
    sockets = []
    count = 0
    print "[client] start..."

    while True:
        try:
            sock = socket.socket()
            sock.connect(('127.0.0.1', PORT))
            count += 1
            try:
                sock.recv(1024)
            except:
                pass
            sockets.append(sock)

            if count % 100 == 0:
                print "[client] total: %d , CLOSE_WAIT: %d" % (count, len(sockets))

        except Exception, e:
            print "[client] stop: %s" % e
            print "CLOSE_WAIT num:", len(sockets)
            while 1:
                time.sleep(1)

启动以后会把本地随机端口用光。

然后我们开新创建手工使用curl命令链接也会是一样的效果。

甚至我们使用telnet测试连通性一样的情况

解决客户端随机端口耗尽 & CLOSE_WAIT 问题:

  1. 提升本机随机端口范围,扩大可用端口数量。
  2. 开启端口复用,让 TIME_WAIT 状态的端口可以快速重用。
  3. 修复程序 BUG,客户端及时关闭 Socket,消除 CLOSE_WAIT 堆积。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-03-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维小路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 解决客户端随机端口耗尽 & CLOSE_WAIT 问题:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档