linux下获取进程网络链接状况(包括打开的侦听端口号)
来源:互联网 发布:数据录入 招聘 编辑:程序博客网 时间:2024/05/28 01:36
在做一个本地服务(服务器端和客户端在同一个机器上,通过回环端口直接访问)时,因为端口可能会被其他程序占用,服务器端会尝试找到一个可用端口,客户端需要逐个尝试连接各个端口,并且与服务器端完成一个验证过程,才能最终确认服务器端的侦听端口。即使双方可以约定从某个端口开始,每次加1尝试,提高发现效率,但是实现起来还是要费一番心事的。
有没有办法直接获得服务器端程序侦听的端口号呢?
我们知道netstat 能够输出socket信息,并且当指定-p选项时,可以输出该socket所属进程的pid和名称,另一个命令 lsof 可以输出进程打开的文件描述符的信息,既然他们能够获取到这些信息,那就应该有办法获取获得服务器端程序侦听的端口号。
没有这两个命令的源代码,那就用 strace 破解吧,用 strace lsof -p 16805 2> log 将lsof调用的系统函数过程保存起来。
lsof 的输出结果最后几行显示了侦听端口,分别是9006、9003:
test 16805 root 8u 0000 0,9 0 963 anon_inodetest 16805 root 9r FIFO 0,8 0t0 127986 pipetest 16805 root 10w FIFO 0,8 0t0 127986 pipetest 16805 root 11u 0000 0,9 0 963 anon_inodetest 16805 root 12r FIFO 0,8 0t0 127987 pipetest 16805 root 13w FIFO 0,8 0t0 127987 pipetest 16805 root 14u IPv4 127999 0t0 TCP *:9006 (LISTEN)test 16805 root 15u IPv4 127992 0t0 TCP *:9003 (LISTEN)
打开log文件,其中与16805这个进程相关的部分如下:
open("/proc/16805/fd", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 4getdents64(4, /* 18 entries */, 32768) = 432readlink("/proc/16805/fd/0", "/dev/pts/0"..., 4096) = 10lstat64("/proc/16805/fd/0", {st_mode=S_IFLNK|0700, st_size=64, ...}) = 0stat64("/proc/16805/fd/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0open("/proc/16805/fdinfo/0", O_RDONLY|O_LARGEFILE) = 7fstat64(7, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78a6000read(7, "pos:\t0\nflags:\t0100002\n", 1024) = 22close(7) = 0munmap(0xb78a6000, 4096) = 0readlink("/proc/16805/fd/1", "/dev/pts/0", 4096) = 10lstat64("/proc/16805/fd/1", {st_mode=S_IFLNK|0700, st_size=64, ...}) = 0stat64("/proc/16805/fd/1", {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0open("/proc/16805/fdinfo/1", O_RDONLY|O_LARGEFILE) = 7fstat64(7, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78a6000read(7, "pos:\t0\nflags:\t0100002\n", 1024) = 22close(7) = 0munmap(0xb78a6000, 4096) = 0readlink("/proc/16805/fd/2", "/dev/pts/0", 4096) = 10lstat64("/proc/16805/fd/2", {st_mode=S_IFLNK|0700, st_size=64, ...}) = 0stat64("/proc/16805/fd/2", {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0open("/proc/16805/fdinfo/2", O_RDONLY|O_LARGEFILE) = 7fstat64(7, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78a6000
可以看到,lsof 对 /proc/16805/fd 目录下的所有文件都调用了readlink,又读入 /proc/16805/fdinfo 目录下的所有文件。
fd目录下的文件都是符号链接,用ls -l /proc/16805/fd 可以看到侦听套接字显示为socket:[127999],但是[]里面的数字代表什么呢?
l-wx------ 1 zenzhang zenzhang 64 2012-07-24 14:48 10 -> pipe:[127986]lrwx------ 1 zenzhang zenzhang 64 2012-07-24 14:48 11 -> anon_inode:[eventpoll]lr-x------ 1 zenzhang zenzhang 64 2012-07-24 14:48 12 -> pipe:[127987]l-wx------ 1 zenzhang zenzhang 64 2012-07-24 14:48 13 -> pipe:[127987]lrwx------ 1 zenzhang zenzhang 64 2012-07-24 14:48 14 -> socket:[127999]lrwx------ 1 zenzhang zenzhang 64 2012-07-24 14:48 15 -> socket:[127992]
lsof 的 trace log 里面内容比较多,我们通过open作为关键字过滤一下:grep open log,发现中间还打开的其他一些文件:
open("/proc/16805/fdinfo/13", O_RDONLY|O_LARGEFILE) = 7open("/proc/16805/fdinfo/14", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/ax25", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)open("/proc/net/ipx", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)open("/proc/net/raw", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/packet", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/unix", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/raw6", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/sockstat6", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/tcp6", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/udp6", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/udp6lite", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)open("/proc/net/sockstat", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/tcp", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/udp", O_RDONLY|O_LARGEFILE) = 7open("/proc/net/udplite", O_RDONLY|O_LARGEFILE) = 7open("/proc/16805/fdinfo/15", O_RDONLY|O_LARGEFILE) = 7open("/proc/16919/stat", O_RDONLY|O_LARGEFILE) = 4
看来秘密就在 /proc/net 下面的这些文件上了,我们侦听的是tcp套接字,先看看 /proc/net/tcp(cat /proc/net/tcp)
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode 0: 00000000:2328 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1006 0 128682 1 c53617c0 300 0 0 2 -1 1: 0100007F:232A 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 149130 1 f0fbb900 300 0 0 2 -1 2: 00000000:070A 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1006 0 128694 1 c5361300 300 0 0 2 -1 3: 0100007F:0CEA 00000000:0000 0A 00000000:00000000 00:00000000 00000000 118 0 5207 1 efcd17c0 300 0 0 2 -1 4: 00000000:232B 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1006 0 127992 1 f0fbaf80 300 0 0 2 -1 5: 0100007F:200B 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 35424 1 efcd2ac0 300 0 0 2 -1 6: 00000000:232E 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1006 0 127999 1 f0fbc740 300 0 0 2 -1 7: 00000000:006F 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 3597 1 f0fb8000 300 0 0 2 -1 8: 00000000:0015 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 7372 1 f0fb8e40 300 0 0 2 -1 9: 00000000:8E16 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 3893 1 efcd04c0 300 0 0 2 -1 10: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 3822 1 efcd0000 300 0 0 2 -1 11: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 108473 1 f0fbf6c0 300 0 0 2 -1 12: 00000000:A63A 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 4600 1 efcd0e40 300 0 0 2 -1 13: 00000000:EC20 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 4664 1 f0fb84c0 300 0 0 2 -1 14: 00000000:0801 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 4580 1 efcd0980 300 0 0 2 -1 15: 6401A8C0:0016 D82DA8C0:F083 01 00000000:00000000 02:0009590E 00000000 0 0 151552 2 c5362600 31 4 3 4 -1 16: 6401A8C0:0016 D12DA8C0:0534 01 00000044:00000000 01:00000026 00000000 0 0 59851 4 efcd3440 39 4 11 5 6 17: 0100007F:232A 0100007F:EB6E 08 00000000:00000000 00:00000000 00000000 1000 0 149133 1 c5360000 20 4 0 2 -1 18: 6401A8C0:0016 382DA8C0:0633 01 00000000:00000000 02:0000DA5D 00000000 0 0 35227 2 efcd2600 22 4 0 4 4 19: 6401A8C0:0016 43C9A8C0:237F 01 00000000:00000000 02:00034FE4 00000000 0 0 109890 2 efcd1300 34 4 30 4 3 20: 6401A8C0:0016 DD01A8C0:79EA 01 00000000:00000000 02:00085BE7 00000000 0 0 126031 2 efcd5580 22 4 12 17 16 21: 6401A8C0:0016 392DA8C0:C3C8 01 00000000:00000000 02:00094AF5 00000000 0 0 7952 2 efcd2140 42 4 26 4 3
果然,里面有那个奇怪的数字"127999"(红色行),根据说明,第一列是本地地址端口(local_address),那应该就是侦听端口了,00000000:232E,16机制转换后果然是9006。
所以通过下列步骤,可以获取进程打开的侦听端口号:
- 枚举 /proc 目录,通过进程文件名找到进程id,用 /proc/<pid>/exe 符号链接匹配文件名
- 枚举 /proc/<pid>/fd 目录,找到进程打开的所有文件描述符(符号链接),其中链接内容为socket:[id]的就是连接套接字,读取其id
- 读取 /proc/net/tcp 文件,找到第9列内容等于套接字id的的行
- 读取local_address列,获得端口号,如果远端地址(rem_address)全是0,就是侦听套接字
- linux下获取进程网络链接状况(包括打开的侦听端口号)
- windows下获取进程网络链接状况(包括打开的侦听端口号)
- linux c 实现 获取系统内存,某进程cpu利用率,以及某端口的网络状况
- Linux 下查看侦听端口
- linux查看网络链接状况命令
- Linux查看网络链接状况命令
- Linux查看网络链接状况命令
- 如何查看Linux下进程的IO活动状况
- Linux下获取进程完整路径(包括进程名)——完整实例代码实现
- 多进程侦听同一端口
- 多进程侦听同一端口
- 多进程侦听同一端口
- windows下进程tcp端口的获取
- linux下查看端口对应的进程号
- Linux下查端口占用的进程
- linux下查看端口对应的进程
- Linux下查询端口占用的进程
- windows下查找打开端口的进程,并关闭
- 开发理念和用户体验
- MOOON-server新消息处理接口
- 不再担心日志文件过大:通用日志滚动脚本
- Dash与Bash的语法区别
- PHP使用BC Math 函数处理浮点运算问题
- linux下获取进程网络链接状况(包括打开的侦听端口号)
- js点滴
- VB.NET中时间转换问题
- perl 进程2
- Linux下Socket写http协议下载文件代码以及说明
- 测试大牛的blog
- 享元模式(Flyweight Pattern)
- PHP判断字符串相等或不等
- 深入浅出C++虚函数表