Что происходит в bind call? (питон + сокет + стрейс) - PullRequest
2 голосов
/ 14 марта 2012

Для пинка я написал следующий эхо-сервер на python. 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)  

За вышеприведенным выводом стриса следует следующий вывод. Вывод выше происходит только в 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 Ответ

3 голосов
/ 14 марта 2012

Я ожидаю, что этой строке будет предшествовать что-то вроде

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' (для «привязки к любому адресу на любом интерфейсе»), вы больше не увидите этот небольшой обмен.

...