查找已连接套接字

时间:2017-04-27 13:41:33

标签: linux sockets networking glibc

我需要找到套接字使用的特定接口,以便我可以使用sysfs文件(/sys/class/net/<IF>/statistics/etc)保留它的统计信息。

我在下面的测试代码中尝试了两种不同的方法,但都失败了。第一个连接到远程服务器,并将ioctlSIOCGIFNAME一起使用,但由于没有这样的设备而失败了#39;第二个使用带有getsockopt的{​​{1}},但这又失败了(它将名称长度设置为0)。

有关这些失败原因或如何获取I / F名称的任何想法?在编译之后,将测试代码运行为SO_BINDTODEVICE,其中test "a.b.c.d"是正在侦听端口80的任何IPV4地址。请注意,我已经在Centos 7上编译了这个,但是没有似乎在a.b.c.d中有IFNAMSZ,因此您可能需要注释掉<net/if.h>行才能在其他系统上进行编译。

感谢。

修改

我发现这实际上是How can I get the interface name/index associated with a TCP socket?的欺骗,所以我应该删除它。 (仅)其中一个答案是正确的(https://stackoverflow.com/a/37987807/785194) - 使用#define IFNAMSZ获取您的本地IP地址,然后在getsockname返回的列表中查找此地址。

关于套接字本质上是动态的一般问题(在下面提到,在另一个问题中多次提到):不太相关。我检查了内核源代码,套接字有一个接口索引和接口名称,API包含至少三种获取当前名称的方法,以及从索引中查找名称的其他例程,反之亦然。但是,索引是somtimes零,这是无效的,这就是下面的getifaddrs版本失败的原因。不知道getsockopt失败的原因。

ioctl

1 个答案:

答案 0 :(得分:1)

TCP(和UDP)套接字未绑定到接口,因此实际上无法回答此查询。现在一般是正确的,给定套接字最终会根据对等端点的地址将数据包传递到特定接口,但是在套接字中没有编码。这是一个动态制定的路由决策。

例如,假设您正在与不直接位于本地LAN上的远程对等方进行通信。并且假设您通过eth0将默认网关配置为192.168.2.1。没有什么可以阻止你通过eth1配置第二个网关,比如192.168.3.1,然后关闭eth0。只要新网关也可以到达远程IP,现在可以使用eth1到达目的地,并且您的会话应该不间断地继续。

因此,如果您需要此信息,您需要从路由条目中推断出它(但要意识到它不能保证是静态的,即使在实践中它可能也是如此)。您可以从getpeername(2)获取同伴的地址。然后,您可以检查可用的路线,以确定哪一条路线可以到达那里。

为此,您可以自己解析和解释/proc/net/route,或者您可以只询问ip命令。例如,我到(任意)ibm.com地址的路由通过我的eth0接口,并将套接字连接到那里,我的本地地址将是192.168.0.102(应该与连接套接字上的getsockname(2)匹配):

$ ip route get 129.42.38.1
129.42.38.1 via 192.168.0.1 dev eth0  src 192.168.0.102
cache