netstat工作原理
netstat命令是linux系统中查看网络情况的一个命令。比如我们可以通过netstat -ntlp | grep 8080
查看监听8080端口的进程。
netstat工作原理如下:
- 通过读取/proc/net/tcp 、/proc/net/tcp6文件,获取socket本地地址,本地端口,远程地址,远程端口,状态,inode等信息
- 接着扫描所有/proc/[pid]/fd目录下的的socket文件描述符,建立inode到进程pid映射
- 根据pid读取/proc/[pid]/cmdline文件,获取进程命令和启动参数
- 根据2,3步骤,即可以获得1中对应socket的相关进程信息
我们可以做个测试验证整个流程。先使用nc命令监听8090端口:
1 | nc -l 8090 |
找到上面nc进程的pid,查看该进程所有打开的文件描述符:
1 | vagrant@vagrant:/proc/25556/fd$ ls -alh |
上面列出的所有文件描述中,socket:[2226056]
为nc命令监听8090端口所创建的socket。其中2226056
为该socket的inode。
根据该inode号,我们查看/proc/net/tcp
对应的记录信息,其中1F9A
为本地端口号,转换成十进制恰好为8090:
1 | vagrant@vagrant:/proc/25556/fd$ cat /proc/net/tcp | grep 2226056 |
根据进程id,我们查看进程名称和启动参数:
1 | vagrant@vagrant:/proc/25556/fd$ cat /proc/25556/cmdline |
下面我们看下/proc/net/tcp
文件格式。
/proc/net/tcp文件格式
/proc/net/tcp
文件首先会列出所有监听状态的TCP套接字,然后列出所有已建立的TCP套接字。我们通过head -n 5 /proc/net/tcp
命令查看该文件头五行:
1 | sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode |
每一行各个字段解释说明如下,由于太长分为三部分说明:
第一部分:
1 | 46: 010310AC:9C4C 030310AC:1770 01 |
上面连接状态所有值如下,具体参见linux源码tcp_states.h:
1 | enum { |
第二部分:
1 | 00000150:00000000 01:00000019 00000000 |
timer_active所有值与说明如下:
- 0 no timer is pending
- 1 retransmit-timer is pending
- 2 another timer (e.g. delayed ack or keepalive) is pending
- 3 this is a socket in TIME_WAIT state. Not all fields will contain data (or even exist)
- 4 zero window probe timer is pending
第三部分:
1 | 1000 0 54165785 4 cd1e6040 25 4 27 3 -1 |
Go实现简易版本netstat命令
netstat工作原理和/proc/net/tcp
文件结构,我们都已经了解了,现在可以使用据此使用Go实现一个简单版本的netstat命令。
核心代码如下,完整代码参加go-netstat:
1 | // 状态码值 |