knetstat 是一个简单的 Linux 内核模块,它向/proc/net
添加了四个新文件: tcpstat
、 tcp6stat
、 udpstat
和udp6stat
。这些文件的内容大致相当于分别带有选项-t4an
、 -t6an
、 -u4an
和-u6an
的netstat
的输出,即它们以人类可读的形式提供有关 TCP 和 UDP 套接字的信息。与相应的netstat
输出的区别在于它们有一个附加列,用于显示套接字选项(的子集)。这是编写 knetstat 内核模块的主要动机:目前,在 Linux 上,管理员无法检查某个进程创建的套接字上设置的选项(除了在创建套接字时在该进程上使用strace
或等效工具) /configuration time),因为此信息不通过/proc
文件系统公开。
knetstat 在内部重用内核使用的基础结构来生成/proc/net/tcp
、 /proc/net/tcp6
、 /proc/net/udp
和/proc/net/udp6
文件的内容。这意味着这些文件中的条目与 knetstat 生成的文件中的条目之间存在一一对应的关系。两者之间仅格式和信息内容不同。
这是一些示例输出:
$ cat /proc/net/tcpstat
Recv-Q Send-Q Local Address Foreign Address Stat Diag Options
0 0 127.0.0.1:6010 0.0.0.0:* LSTN SO_REUSEADDR=1,SO_KEEPALIVE=0,TCP_NODELAY=0
0 0 0.0.0.0:22 0.0.0.0:* LSTN SO_REUSEADDR=1,SO_KEEPALIVE=0,TCP_NODELAY=0
0 0 192.168.1.18:22 192.168.1.6:49537 ESTB SO_REUSEADDR=1,SO_KEEPALIVE=1,TCP_NODELAY=1
0 0 127.0.0.1:6010 127.0.0.1:45462 ESTB SO_REUSEADDR=1,SO_KEEPALIVE=0,TCP_NODELAY=1
0 0 127.0.0.1:45462 127.0.0.1:6010 ESTB SO_REUSEADDR=0,SO_KEEPALIVE=1,TCP_NODELAY=1
“诊断”栏可显示以下诊断指示器:
指标 | 意义 |
---|---|
>| | 发送方窗口(即远程端点通告的窗口)为0。没有数据可以发送到对等方。 |
|< | 接收者窗口(即本地端点通告的窗口)为0。无法从对端接收到任何数据。 |
># | 有未确认的数据包,并且最后一个 ACK 是在超过一秒之前收到的。这可能表明存在网络问题或对等点崩溃。 |
SO_REUSEADDR
、 SO_REUSEPORT
、 SO_KEEPALIVE
(TCP)、 TCP_KEEPIDLE
(TCP)、 TCP_KEEPCNT
(TCP)、 TCP_KEEPINTVL
(TCP)、 SO_RCVBUF
、 SO_SNDBUF
、 SO_RCVTIMEO
、 SO_SNDTIMEO
、 SO_LINGER
(TCP)、 TCP_NODELAY
、 TCP_FASTOPEN
、 TCP_DEFER_ACCEPT
, SO_BROADCAST
(UDP) TCP_KEEPIDLE、TCP_KEEPCNT 和 TCP_KEEPINTVL 对应于 tcp(7) 和相应 sysctls 中描述的 tcp_keepalive_time、tcp_keepalive_probes 和 tcp_keepalive_intvl 值。如果这些值在套接字级别被覆盖(通过将它们设置为零以外的值),它们将由 knetstat 打印,否则,内核将使用 sysctls 并且模块将在打印输出时忽略它们。
当前的 knetstat 代码已在内核版本 3.13、3.18、4.4、4.8、4.9 和 4.15 上成功测试。它也可以与其他版本一起使用。
要构建模块,请确保您拥有当前运行的内核的标头以及基本构建工具(例如 make 和 GCC)。例如在 Ubuntu 上:
# apt-get install linux-headers-$(uname -r) make gcc
然后查看 knetstat 源代码并执行make
。这应该创建knetstat.ko
,可以使用insmod
加载它。
下表显示了 knetstat 报告的套接字选项与java.net.Socket
类定义的 setter 方法之间的对应关系。此信息可用于根据 knetstat 的输出推断 Java 进程应用于java.net.Socket
实例的配置。除了setSoTimeout
之外,映射很简单。
Java方法 | knetstat 报告的套接字选项 |
---|---|
setKeepAlive | SO_KEEPALIVE |
setReceiveBufferSize | SO_RCVBUF |
setReuseAddress | SO_REUSEADDR |
setSendBufferSize | SO_SNDBUF |
setSoLinger | SO_LINGER |
setSoTimeout | 没有任何 [*] |
setTcpNoDelay | TCP_NODELAY |
[*] 与 Javadoc 的建议相反, setSoTimeout
方法实际上并未在 Linux 上设置任何套接字选项。默认情况下, java.net.Socket
实例由java.net.SocksSocketImpl
支持(即使未配置 SOCKS 代理)。此类扩展了java.net.AbstractPlainSocketImpl
,它在内部存储超时以供java.net.SocketInputStream
中的读取方法稍后使用。它们反过来将超时传递给poll
系统调用的调用,该调用等待数据可供读取(或发生错误)。