2015-12-21 2 views
0

У меня есть клиентская программа, которая использует два сокета UDP, один для прослушивания, а другой для записи.Python: UDP сокет recvfrom возвращает localhost или внешний IP

OUT_SOCKET = socket(AF_INET, SOCK_DGRAM) # write-only UDP 
IN_SOCKET = socket(AF_INET, SOCK_DGRAM) # read-only UDP 

Я запускаю программу на локальном хосте на двух разных портах и ​​отправляю сообщения друг другу.

OUT_SOCKET.sendto(some_msg, (ip, port)) 

И я прочитал это сообщение.

msg, addr = IN_SOCKET.recvfrom(MAX_MSG_SIZE) 

Проблема заключается в том, когда я указать 127.0.0.1 для IP (для отправки some_msg), на принимающем клиента, addr установлен на 127.0.0.1. Но когда я укажу ip от 192.168.X.X (мой внешний IP-адрес) от отправки клиента, addr принимающего клиента устанавливается в 192.168.X.X.

Я ожидаю, что addr будет соответствовать независимо от того, как ip установлен. recvfrom ведет себя по-разному в зависимости от того, как отправитель указывает IP-адрес?

Как извлекать удаленный адрес? Что заставляет recvfrom вести себя по-другому?

+0

Возможно, я что-то пропустил, но его IP-адрес отправителя. Когда клиент отправляет сообщение «192.168.X.X», он отправляет на внешний IP-интерфейс устройства так, как и следовало ожидать. '127.0.0.1' не должен попадать во внешнюю сеть, потому что там нет смысла. – tdelaney

+0

@tdelaney Ну, как отправитель, так и получатель находятся на моей локальной машине. Поэтому я подумал, что для addr имеет смысл 127.0.0.1 или 192.168.X.X, потому что отправитель является моей машиной. Но странно, что иногда это 127.0.0.1, а иногда это 192.168.X.X. Мне было интересно, что будет причиной непоследовательности. – mark

+0

Это два разных интерфейса, которые не направляются друг к другу, поэтому они действуют как два отдельных компьютера. Предположим, вы подключили другую сеть '10.0.X.X', которая была отделена от сети 192. Вам нужен адрес '10.0.X.X', отправленный, скажем,' 10.0.0.99', иначе он не знал бы, как отправить что-то обратно вам. – tdelaney

ответ

1

Адрес, возвращенный с recvfrom, является именно исходным IP-адресом в полученном пакете. Когда вы отправляете UDP-пакет с использованием sendto, IP-стек выберет соответствующий интерфейс для отправки пакета. recvfrom не ведет себя иначе, sendto выбирает исходный сетевой интерфейс на основе правил IP-маршрутизации.

В вашем случае у вас есть два сетевых интерфейса: один, который прослушивает пакеты с адресом назначения 127.0.0.1 и другой, который прослушивает 192.168.x.y. Когда вы отправляете пакет с использованием sendto, он должен исходить из сетевого интерфейса, который может маршрутизировать на целевой адрес.

Когда вы отправляете пакет в 127.0.0.1, он будет исходить из обратного адреса (например, 127.0.0.1). Когда вы отправляете пакет в 192.168.x.y, он будет исходить из второго сетевого интерфейса. В обоих случаях IP-адрес однорангового узла, возвращаемый с recvfrom, идентифицирует передающий сетевой интерфейс.

+0

Его исходный адрес отправителя, чтобы вы знали, кто его отправил. – tdelaney

+1

Я не думаю, что это правильно. Документ говорит: Возвращаемое значение представляет собой пару (строка, адрес), где строка представляет собой строку, представляющую полученные данные, а адрес - адрес сокета, отправляющего данные. – mark

+0

@mark - понятия не имею, о чем я думал, когда писал свой оригинальный ответ. Я переписал ответ;) –

Смежные вопросы