从/proc读取TCP连接列表

从/proc读取TCP连接列表

我正在尝试实现枚举每个进程的所有现有 TCP 连接的代码(类似于netstat -lptn)。我更喜欢自己实现而不是依赖netstat。为了做到这一点,我正在解析来自 的数据/proc/<PID>/net/tcp

我看到下面列出了许多 TCP 连接,/proc/<PID>/net/tcp但没有通过命令列出netstat -lptn

例如,我看到了这一点/proc/1/net/tcp,并且/proc/2/net/tcp有几个 TCP 连接(在 Ubuntu 16 上尝试过)。据我了解,与不应有任何 TCP 连接的进程/proc/1/net/tcp有关。与之/sbin/init相关/proc/2/net/tcpkthreadd也不应该有任何 TCP 连接。

答案1

您的方法存在很多误解。我将一一回顾它们。

  1. 套接字不与特定进程关联。创建套接字时,其引用计数为 1。但是通过不同的方法(例如dup2fork和文件描述符传递),可能会创建对同一套接字的许多引用,导致其引用计数增加。其中一些引用可以来自打开的文件描述符表,该表本身可以被许多线程使用。这些线程可能属于相同的线程组(PID)或不同的线程组。当您使用该-p标志时,netstat它将枚举每个进程可访问的套接字,并尝试为每个已知套接字查找进程。如果有多个候选进程,则不能保证它显示您感兴趣的进程。
  2. /proc/<PID>/net/tcp不仅列出与该进程相关的套接字。它列出了该进程所属的网络命名空间中的所有 TCPv4 套接字。在默认配置中,系统上的所有进程都属于单个网络命名空间,因此您将看到任何 PID 都相同的结果。这也解释了为什么不使用网络的线程/进程在此文件中包含内容。即使它本身不使用网络,它仍然属于其他进程可以使用网络的网络命名空间。
  3. /proc/<PID>/net/tcp包含侦听和连接的套接字。当你传递-lnetstat它时,只会显示正在监听的套接字。为了更接近地匹配输出,您需要-a而不是-l.
  4. /proc/<PID>/net/tcp仅包含 TCPv4 套接字。您/proc/<PID>/net/tcp6还需要使用它来查看所有 TCP 套接字。

如果您只对与您自己的进程位于同一命名空间中的套接字感兴趣,则无需迭代不同的 PID。您可以改为使用/proc/net/tcpandsince/proc/net/tcp6/proc/net的符号链接/proc/self/net

答案2

使用/proc/<pid>/fd- 列出所有打开的文件描述符,包括进程正在使用的套接字。例如

/proc/1278482/fd:
total 0
dr-xr-xr-x. 9 user user  0 Apr 22 23:30 ../
dr-x------. 2 user user  0 Apr 22 23:30 ./
lr-x------. 1 user user 64 Apr 22 23:30 4 -> pipe:[640683476]
lrwx------. 1 user user 64 Apr 22 23:30 3 -> socket:[640754628]
lrwx------. 1 user user 64 Apr 22 23:30 2 -> /dev/pts/10
l-wx------. 1 user user 64 Apr 22 23:30 1 -> /home/user/my_sockets.txt
lrwx------. 1 user user 64 Apr 22 23:30 0 -> /dev/pts/10

然后您可以从中找到相应的条目(例如640754628)/proc/<pid>/net/tcp -> inode[6]以获取套接字的所有详细信息 - 例如

tcp:
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
1864: 0100007F:A650 0100007F:18EB 01 00000000:00000000 00:00000000 00000000   500        0 640754628 1 0000000000000000 20 4 30 10 -1

(上面的示例是到 127.0.0.1:6379 的本地连接)

相关内容