Вопрос

Я нахожусь в процессе реализации сервиса - написанного на 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 (...) .

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top