Как сделать разблокировку соединения с сервера в Twisted?

Я реализую API со следующей базовой структурой:

  1. Запустить serverA
  2. Клиент подключается к serverA и отправляет данные
  3. ServerA обрабатывает данные и отправляет их на serverB
  4. ServerB отвечает serverA
  5. ServerA отвечает на запрос клиента на основе входных данных, полученных от serverB

Пока что я пробовал два решения:

1) Создайте стандартное TCP-соединение без витой пары, используя httplib для обработки запроса от serverA к serverB. Однако это эффективно блокирует сервер на время вызова httplib.

2) Создайте второй класс, наследующий от protocol.Protocol и используйте

factory = protocol.ClientFactory()
factory.protocol = Authenticate
reactor.connectSSL("localhost",31337,factory, ssl.ClientContextFactory())

для создания соединения между serverA и serverB. Однако при этом я, похоже, не могу получить доступ к исходному соединению клиент-серверA из обратных вызовов класса запроса.

Как правильно обрабатывать такую ​​настройку в Twisted?


person 0x90    schedule 30.11.2012    source источник


Ответы (1)


Соединение «клиент-серверA» представлено экземпляром протокола, связанным с транспортом. Это обычные старые объекты Python, поэтому вы можете делать такие вещи, как передавать их в качестве аргументов функциям или инициализаторам классов или устанавливать их как атрибуты для других объектов.

Например, если у вас есть ClientToServerAProtocol с методом fetchServerBData, который вызывается в ответ на несколько байтов, полученных от клиента, вы можете записать его примерно так:

class ClientToServerAProtocol(Protocol):
    ...
    def fetchServerBData(self, anArg):
        factory = protocol.ClientFactory()
        factory.protocol = Authenticate
        factory.clientToServerAProtocol = self
        reactor.connectSSL("localhost",31337, factory, ssl.ClientContextFactory())

Поскольку ClientFactory устанавливает себя как атрибут factory в любом создаваемом протоколе, экземпляр Authenticate, который появится в результате этого, сможет сказать self.factory.clientToServerAProtocol и получить ссылку на это соединение «клиент-серверA».

Есть много вариантов этого подхода. Вот еще один, использующий недавно представленный API конечных точек:

from twisted.internet.endpoints import SSL4ClientEndpoint

class ClientToServerAProtocol(Protocol):
    ...
    def fetchServerBData(self, anArg):
        e = SSL4ClientEndpoint(reactor, "localhost", 31337, ssl.ClientContextFactory()) 
        factory = protocol.Factory()
        factory.protocol = Authenticate
        connectDeferred = e.connect(factory)
        def connected(authProto):
            authProto.doSomethingWith(self)
        connectDeferred.addCallback(connected)

Здесь та же основная идея - используйте self для ссылки на интересующее вас соединение «клиент-серверA» с протоколом Authenticate. Здесь я использовал вложенную функцию, чтобы "закрыть" self. Это всего лишь еще один из множества вариантов, которые у вас есть для получения ссылок на нужную часть вашей программы.

person Jean-Paul Calderone    schedule 30.11.2012