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_LINGER
SO_REUSEPORT
、 SO_KEEPALIVE
( SO_RCVTIMEO
)、 TCP_KEEPIDLE
( SO_SNDTIMEO
)、 TCP_KEEPCNT
( TCP_DEFER_ACCEPT
TCP_NODELAY
、 TCP_KEEPINTVL
(TCP)、 SO_RCVBUF
、 SO_SNDBUF
TCP_FASTOPEN
、 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
系統調用的調用,該調用等待資料可供讀取(或發生錯誤)。