在Python中查询TCP套接字连接状态

9
当我在Python中打开网络连接时,如下所示:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('www.heise.de', 80))

我可以从控制台读取连接状态:
netstat --all --program|grep <PID>
tcp   0  0 10.10.10.6:39328   www.heise.de:http  VERBUNDEN  23829/python

但是我该如何在Python中读取连接状态,例如CONNECTED,CLOSE_WAIT等?阅读socket文档并没有给我任何提示。


你正在混淆套接字状态、端口状态和连接状态。这三者并不相同。 - user207421
3个回答

12

这仅适用于Linux操作系统:

您需要使用getsockopt调用。level是"IPPROTO_TCP",选项是"TCP_INFO",正如tcp手册所建议的那样。它将返回tcp_info数据,该数据在此处定义,您还可以在此找到STATE值的枚举。

您可以尝试此示例:

    import socket
    import struct

    def getTCPInfo(s):
        fmt = "B"*7+"I"*21
        x = struct.unpack(fmt, s.getsockopt(socket.IPPROTO_TCP, socket.TCP_INFO, 92))
        print x

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    getTCPInfo(s)
    s.connect(('www.google.com', 80))
    getTCPInfo(s)
    s.send("hi\n\n")
    getTCPInfo(s)
    s.recv(1024)
    getTCPInfo(s)

您要查找的是打印元组中的第一个项目(整数)。您可以使用tcp_info定义交叉检查结果。

注意:tcp_info的大小应该为104,但我用92使其工作,不确定发生了什么,但对我而言它起作用了。


很遗憾,没有更高级的函数可以实现那个。不过还是感谢你指出了如何做到这一点。对我来说,92听起来像是7+4*21+1(终端0)。 - Michael
6
根据此链接,“struct.unpack("B"*7+"I"*24, s.getsockopt(socket.SOL_TCP, socket.TCP_INFO, 104))”更完整。 - est
不确定这在2019年是否仍然流行,但是这里有两个澄清:
  1. 大小必须是4的倍数。因为Python将使用这4个“单位”来表示一个十六进制数。
  2. 要获取您机器的正确大小,您需要查看 /usr/include/linux/tcp.h 并查看那里定义了多少个字段以及是什么类型。u_8 是 (1),u_32 是 (4),u_64 是 (8) 等等。因此,请查看您感兴趣的值并使用 unpack 解码它们。要检查在获得正确格式后所需的确切大小,可以使用 struct 模块中的 calcsize()。
- Misho Janev

1

我刚刚用胶带拼凑出了这个问题的一半解决方案,以防万一谷歌会把其他人带到这里。

import urllib2
import psutil

page = urllib2.urlopen(URL) # dummy URL
sock = page.fp              # The socket object that's being held open
fileno = sock.fileno()

proc = psutil.Process()
connections = proc.connections()
matches = [x for x in connections if x.fd == fileno]
if not matches:
    status = None
else:
    assert len(matches) == 1
    match = matches[0]
    status = match.status

一旦确定了这个套接字,下一步该做什么还有待商榷。


0
在Linux上,您可以使用getsockopt(2)TCP_INFO选项来了解连接的状态。

s.getsockopt() 需要两个选项,level 和 option。我猜 TCP_INFO 是 option。那 level 我该用什么?我试了一些值,但都不行。 - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接