Twisted: исходный IP-адрес для исходящих соединений - PullRequest
3 голосов
/ 26 октября 2009

Я нахожусь в процессе реализации сервиса - написанного на Python с использованием Twisted Framework, работающего на Debian GNU / Linux - который проверяет доступность SIP-серверов. Для этого я использую метод OPTIONS (функция протокола SIP), так как это кажется обычной практикой. Чтобы создать правильные и совместимые с RFC заголовки, мне нужно знать IP-адрес источника и порт источника для соединения, которое будет установлено. [Как] это можно сделать с помощью Twisted?

Вот что я попробовал: Я вложил в подкласс protocol.DatagramProtocol , а внутри startProtocol(self) я использовал self.transport.getHost().host и self.transport.getHost().port. Последний действительно является портом, который будет использоваться, тогда как первый дает только 0.0.0.0.

Полагаю, что на данный момент Twisted еще не знает, какой интерфейс и как какой IP-адрес источника будет использоваться. Предоставляет ли Twisted средство, которое может помочь мне в этом, или мне нужно по-другому взаимодействовать с ОС (маршрутизацией)? Или я просто неправильно использовал self.transport.getHost().host

Ответы [ 3 ]

8 голосов
/ 18 ноября 2009

Ради полноты отвечаю на свой вопрос:

Убедитесь, что вы используете connect () для транспорта, прежде чем пытаться определить IP-адрес источника хоста. Следующий отрывок показывает соответствующую часть реализации протокола:

class FooBarProtocol(protocol.DatagramProtocol):
    def startProtocol(self):
        self.transport.getHost().host   # => 0.0.0.0
        self.transport.connect(self.dstHost, self.dstPort)
        self.transport.getHost().host   # => 192.168.1.102
0 голосов
/ 01 ноября 2009

Видели ли вы, что вы хотите сделать, с реализацией SIP, которая является частью Twisted?

В любом случае, как вы устанавливаете адрес источника и порт для UDP в Twisted, очень похоже на то, как вы устанавливаете их без Twisted. В Twisted reactor.listenUDP(port, protocol, interface) привязывает сокет UDP к определенному порту и интерфейсу и обрабатывает полученные дейтаграммы в вашем протоколе. Внутри протокола self.transport.write(msg, addr) отправляет дейтаграмму на addr, используя адрес, с которым протокол связан как адрес источника.

Читая ваш вопрос еще раз, я думаю, единственная часть, которую вы пропустили, передавала interface reactor.listenUDP(...).

0 голосов
/ 26 октября 2009

Если вы используете UDP, тогда конечная точка определяется либо:

  1. вызов bind() на сокете и явное присвоение ему адреса
  2. отправка пакета

Если вам нужны дополнительные сведения, проверьте этот ответ .

Проблема в том, что я не настолько знаком с витой. Из того, что я могу судить по быстрому изучению источника, похоже, что вы могли бы вместо этого использовать реактор типа t.i.d.SelectReactor. Это то, что t.n.d.DNSDatagramProtocol делает под капотом .

Если вы берете twisted из картинки, то следующий фрагмент показывает, что происходит:

>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
<socket._socketobject object at 0x10025d670>
>>> s.getsockname()           # this is an unbound or unnamed socket
('0.0.0.0', 0)
>>> s.bind( ('0.0.0.0', 0) )  # 0.0.0.0 is INADDR_ANY, 0 means pick a port
>>> s.getsockname()           # IP is still zero, but it has picked a port
('0.0.0.0', 56814)

Получить имя хоста немного сложнее, если вам нужно поддерживать несколько сетевых интерфейсов или IPv4 и IPv6. Если вы можете сделать используемый интерфейс настраиваемым, то передайте его в качестве первого члена кортежа на socket.bind(), и вы настроены.

Теперь трудная часть делает это в рамках абстракций, которые предоставляет витая. К сожалению, я ничего не могу поделать там. Я бы порекомендовал поискать примеры того, как вы можете получить доступ к базовому сокету или найти способ передачи информации о сокете в каркас.

Удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...