linux下读/proc/net/tcp常读不到established连接,因其仅含ipv4连接且状态为十六进制码(01表示established),非字符串;ipv6需查/tcp6,地址为小端十六进制,解析须用sscanf按宽提取并转字节序。

Linux 下直接读 /proc/net/tcp 为什么常读不到 ESTABLISHED 连接?
因为 /proc/net/tcp 默认只显示 IPv4 的 TCP 连接,且状态字段是十六进制数(如 01 表示 ESTABLISHED),不是字符串。很多脚本或 C++ 程序直接用 std::string::find("ESTABLISHED") 肯定失败。
- 状态码需查内核头文件:
01= ESTABLISHED,06= TIME_WAIT,0A= LISTEN —— 不是十进制 - 每行格式固定:索引、本地地址:端口、远端地址:端口、状态、队列、超时、重传、UID、超时时间、inode;地址是十六进制小端(如
0100007F:0016表示 127.0.0.1:22) - IPv6 连接在
/proc/net/tcp6,不能忽略;若只读 tcp,会漏掉所有 IPv6 连接 - 解析时跳过第一行(表头),但有些发行版(如 Alpine)可能没表头,得靠字段数判断是否有效行
C++ 解析 /proc/net/tcp 的最小安全读法
别用 std::ifstream 一行行 getline 后再 stringstream 拆——字段含空格又不严格对齐,容易错位。推荐用 sscanf 或 std::from_chars(C++17)按固定宽度提取。
- 先
open("/proc/net/tcp", O_RDONLY),用read()一次性读入缓冲区,避免/proc文件被并发修改导致半截数据 - 对每行调用:
sscanf(line, "%*d: %64[^:]:%X %64[^:]:%X %X", local_addr, &local_port, remote_addr, &remote_port, &state) -
local_addr和remote_addr是 char 数组,需手动转字节序(inet_ntop(AF_INET, &addr_num, buf, sizeof(buf))) - UID 字段在第 8 列(从 0 开始数),但某些容器环境 UID 为 0 或 -1,不能直接用于权限判断
Windows 上调 GetExtendedTcpTable 为什么返回 ERROR_INSUFFICIENT_BUFFER?
这不是错误,是正常流程。Windows 要求你先传 NULL 获取所需缓冲区大小,再分配内存重试。很多人卡在这步,反复传 NULL 或直接 malloc 固定大小就崩了。
- 第一次调用:
DWORD size = 0; GetExtendedTcpTable(NULL, &size, FALSE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)→ 返回ERROR_INSUFFICIENT_BUFFER,size被设为真实需要字节数 - 第二次:用
malloc(size)分配,再传入该指针;注意结构体是MIB_TCPROW_OWNER_PID数组,首 DWORD 是条目数 - 必须用
AF_INET+TCP_TABLE_OWNER_PID_ALL才能拿到 PID;若用TCP_TABLE_BASIC_ALL,PID 字段无效 - 返回的 PID 可能为 0(系统进程),需用
OpenProcess+QueryFullProcessImageName才能拿到进程名,且要开PROCESS_QUERY_LIMITED_INFORMATION权限
跨平台检测“是否有活跃外连”该怎么写才可靠?
别指望一个函数覆盖所有场景。Linux 和 Windows 的语义差异大:Linux 的 /proc 是快照,Windows 的 GetExtendedTcpTable 是内核查询,但都可能漏掉 UDP、本地回环、或刚关闭的连接。
立即学习“C++免费学习笔记(深入)”;
- 如果目标只是“当前有无到公网 IP 的 ESTABLISHED 连接”,Linux 优先扫
/proc/net/{tcp,tcp6},过滤掉127.0.0.0/8、::1、10.0.0.0/8等私有网段 - Windows 上别只看
dwState == MIB_TCP_STATE_ESTAB,还得检查dwRemoteAddr != 0且非内网地址(需自己实现 CIDR 判断) - UDP 没连接状态,
/proc/net/udp*和GetExtendedUdpTable只能看监听端口,无法判断“是否发过包” - 真正健壮的做法:加一层心跳检测——比如尝试 connect 一个已知稳定的公网地址(如
1.1.1.1:53),超时即认为网络不通;/proc 或 API 结果只是辅助佐证
路径、权限、地址族、状态编码、缓冲区生命周期——这些地方一松动,程序就在不同机器上表现不一致。尤其是容器里 /proc 是挂载的,Windows 上权限弹窗会卡住后台服务。










