绑定调用中发生了什么? (python + socket + strace)

时间:2012-03-14 01:05:55

标签: python linux sockets kernel internals

对于踢,我在python中编写了以下echo服务器。 http://ilab.cs.byu.edu/python/socket/echoserver.html(我想我从这里复制了代码。)

#!/usr/bin/env python

import socket

host = ''
port = 50000
backlog = 5
size = 1024

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))

然后我运行了strace -o / tmp / somefile -v ipython 并开始逐行插入代码片段。

大部分输出都有意义,但我无法理解以下内容。

bind(4, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
getsockname(4, {sa_family=AF_NETLINK, pid=3084, groups=00000000}, [12]) = 0
sendto(4, "\24\0\0\0\26\0\1\3\300EPO\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
recvmsg(4, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0\300EPO\f\f\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 108
recvmsg(4, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"@\0\0\0\24\0\2\0\300EPO\f\f\0\0\n\200\200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 128
recvmsg(4, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0\300EPO\f\f\0\0\0\0\0\0\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20
close(4)  

上面的strace输出后面是以下输出。上面的输出只发生在python2.6。

listen(3, 5)                            = 0
accept(3, {sa_family=AF_INET, sin_port=htons(45636), sin_addr=inet_addr("127.0.0.1")}, [16]) = 4
recvfrom(4, "Hey", 1024, 0, NULL, NULL) = 3
sendto(4, "Heyback", 7, 0, NULL, 0)     = 7
close(4)                                = 0
accept(3, 0x7fffdac55fe0, [16])         = ? ERESTARTSYS (To be restarted)

这是一个学术练习,服务器运行得很好,但我想知道文件描述符4发生了什么?为什么它只出现在python2.6中?

1 个答案:

答案 0 :(得分:3)

我希望这行前面有类似

的内容
socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE) = 4

man 7 netlink告诉我们发送内容的格式,因此我们可以将发送的消息解码为

的串联
struct nlmsghdr _ = {
    .nlmsglen = 20,
    .nlmsg_type = RTM_GETADDR,
    .nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MATCH;
    .nlmsg_seq = 1330660800,
    .nlmsg_pid = 0,
};

和零的四个字节。

什么是RTM_GETADDR? man 7 rtnetlink表示这是对每个接口的IP地址信息的请求。我们可以解码响应主体的struct ifaddrmsg,但每个前面的netlink标题使得strace将数据输出缩短。

无论如何,我很乐意在这里停下来假设它只是检索填写struct sockaddr_in以拨打bind所需的信息。毕竟,你确实传入了一个空的节点名称,所以它没有什么可以解决的。确认这一点,如果您将''更改为'0.0.0.0'(对于“绑定到任何界面上的任何地址”),您将不再看到这个小交换。