c++怎么通过读取/proc/net/tcp解析Linux当前的TCP连接日志【底层】

老丽吖_9388

老丽吖_9388

2026-03-26

879人浏览

原创

直接读取/proc/net/tcp可获取tcp连接快照,但需正确解析十六进制ip(小端转点分十进制)、端口(大端十六进制直接转整数)及状态码(如01→established),且受用户权限限制。

c++怎么通过读取/proc/net/tcp解析linux当前的tcp连接日志【底层】

直接读 /proc/net/tcp 就行,但得懂十六进制地址和状态码

Linux 内核把当前所有 TCP 连接快照写在 /proc/net/tcp 里,是纯文本、无锁、零拷贝的底层接口。它不经过 socket API,也不依赖 netstat/ss,所以最轻量——但格式反人类:IP 和端口全用十六进制小端编码,状态是数字,不是字符串。

常见错误是直接用 std::stoi(line, nullptr, 16) 解 IP 却忘了字节序翻转。比如 0100007F 看着像 127.0.0.1,其实是 7F 00 00 01(小端),得先反转字节再转点分十进制。

  • /proc/net/tcp 第一行是表头,跳过
  • 第2列(local_address)和第3列(rem_address)都是 hex_ip:hex_port 格式
  • 第4列 st 是 TCP 状态,01 = ESTABLISHED,0A = LISTEN,查 include/net/tcp_states.h 或内核文档
  • 第10列 inode 可用来关联 /proc/[pid]/fd/ 下的 socket 文件(需 root 或同用户)

解析端口时别漏掉 ntohs() 的等效操作

C 语言里通常用 ntohs() 把网络字节序端口转为主机序,C++ 没强制依赖 C 库也能做——因为 /proc/net/tcp 里的端口是十六进制大端表示,但值本身已经是网络序,所以只需转成整数再“按主机序解释”即可。实际就是:读出 0017 → 十进制 23 → 它就是 23,不用额外翻字节。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 错误做法:uint16_t port = (hex_val & 0xFF) > 8) ——这是对小端 hex 值二次翻转,错
  • 正确做法:unsigned short port = static_cast<unsigned short>(std::stoul(hex_port_str, nullptr, 16))</unsigned>
  • 注意:std::stoul("0017", nullptr, 16) 返回 23,直接可用

状态码映射必须硬编码,别信字符串匹配

/proc/net/tcp 的 st 字段永远是两位十六进制(如 01、0A),不会变成 ESTABLISHED。想打印可读状态,只能自己建个映射表。内核不会改这个编码规则,但不同内核版本可能新增状态(如 0F = TCP_CLOSE),所以别只覆盖常见几个。

  • 关键状态: "01" → ESTABLISHED,"0A" → LISTEN,"06" → TIME_WAIT,"02" → SYN_SENT
  • 别用 if (st == "01") 字符串比较——效率低且易拼错;用 std::map<:string std::string></:string> 或 switch + std::stoi(st, nullptr, 16)
  • 忽略 st == "00" 的条目,那是未完成连接(如 SYN_RECV 中断后残留)

权限和稳定性:非 root 只能看到本用户的连接

读 /proc/net/tcp 本身不需要 root,但内容受 /proc/sys/net/ipv4/ip_unprivileged_port_start 和进程 UID 限制:普通用户只能看到自己创建的 socket 对应的连接行;root 才能看全量。另外,该文件是瞬时快照,两次读取之间连接可能已消失或新建,不适合做精确计时或状态跟踪。

  • 如果 open() 失败并报 Permission denied,不是路径错,而是你没权限访问该 proc 条目(检查是否被 nsjail/seccomp 拦截)
  • 不要用 fseek 或反复 read() 同一个 fd——内核每次 read 都重新生成内容,fd 无意义
  • 单次读完就 close,别长期持有;频繁调用建议加毫秒级限频,避免触发内核 proc 接口抖动

真正难的不是读文件,是把 0100007F:0017 在脑子里秒变 127.0.0.1:23,以及记住 0A 是监听不是关闭——这些细节不写进代码注释,下次维护准懵。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

2023.09.21

1071

6

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

2024.03.13

1417

13

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.03

1778

5

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

2784

5

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

6124

49

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2023.11.24

5829

6

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

2024.03.22

7454

16

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2024.04.29

11034

11

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

2025.07.29

5659

17

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习