Twisted: исходный IP-адрес для исходящих соединений
-
06-07-2019 - |
Вопрос
Я нахожусь в процессе реализации сервиса - написанного на Python с использованием Twisted Framework, работающего на Debian GNU / Linux - который проверяет доступность SIP-серверов. Для этого я использую метод OPTIONS (функция протокола SIP), так как это кажется обычной практикой. Чтобы построить правильные и совместимые с RFC заголовки, мне нужно знать IP-адрес источника и порт источника для соединения, которое будет установлено. [Как] это можно сделать с помощью Twisted?
Вот что я попробовал:
Я вложил в подкласс protocol.DatagramProtocol и внутри < code> startProtocol (self) Я использовал self.transport.getHost (). host
и self.transport.getHost (). port
. Последний действительно является портом, который будет использоваться, тогда как первый дает только 0.0.0.0.
Я полагаю, что на данный момент Twisted еще не знает, какой интерфейс и как какой IP-адрес источника будет использоваться. Предоставляет ли Twisted средство, которое может помочь мне в этом, или мне нужно по-другому взаимодействовать с ОС (маршрутизацией)? Или я просто неправильно использовал self.transport.getHost (). Host
?
Решение
Ради полноты я отвечу на свой вопрос:
Убедитесь, что вы используете 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
Другие советы
Если вы используете UDP, тогда конечная точка определяется либо:
<Ол> bind ()
для сокета и явное присвоение ему адреса Если вам нужна дополнительная информация, проверьте этот ответ . р>
Проблема в том, что я не настолько знаком с витой. Судя по тому, что я могу быстро узнать из источника, вы можете использовать реактор, например, tidSelectReactor
. Это то, что tndDNSDatagramProtocol
работает под капотом .
Если вы уберете скрученный
с картинки, то в следующем фрагменте показано, что происходит:
>>> 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 ()
и все готово.
Теперь трудная часть делает это в рамках абстракций, которые предоставляет Twisted. К сожалению, я ничего не могу поделать там. Я бы порекомендовал поискать примеры того, как вы можете получить доступ к базовому сокету или найти способ передачи информации о сокете в платформу.
Удачи.
Видели ли вы, что вы хотите сделать, с реализацией SIP, которая является частью Twisted?
В любом случае, как вы устанавливаете адрес источника и порт для UDP в Twisted, очень похоже на то, как вы устанавливаете их без Twisted. В Twisted реактор.listenUDP (порт, протокол, интерфейс)
связывает сокет UDP с конкретным портом и интерфейсом и обрабатывает полученные дейтаграммы с вашим протоколом. Внутри протокола self.transport.write (msg, addr)
отправляет дейтаграмму в addr
, используя адрес, с которым протокол связан как адрес источника.
Читая ваш вопрос еще раз, я думаю, что единственная часть, которую вы пропустили, - это передача interface
в реактор.listenUDP (...)
.