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系统调用的调用,该调用等待数据可供读取(或发生错误)。