Вопрос по дизайну сетевого программирования на Python - PullRequest
3 голосов
/ 22 сентября 2010

В настоящее время я пишу проект на Python, который имеет клиентскую и серверную части. У меня проблемы с сетевым взаимодействием, поэтому мне нужно кое-что объяснить ...

Клиент в основном выполняет операции, которые ему сообщает сервер, и отправляет результаты операций обратно на сервер. Мне нужен способ для передачи двунаправленной информации по TCP-сокету.

Текущая ситуация

В настоящее время я использую LineReceiver Twisted Framework на стороне сервера и простой Python socketssl) на стороне клиента (поскольку я не смог правильно реализовать Twisted PushProducer). На стороне клиента есть Queue, который заполняется данными, которые следует отправлять на сервер; подпроцесс непрерывно извлекает данные из очереди и отправляет их на сервер (см. код ниже).

Этот сценарий работает хорошо, если только клиент передает свои результаты менеджеру. Сервер не может отправлять данные клиенту. Точнее, клиент не может получить данные, отправленные сервером.

Проблема

Мне нужен способ отправки команд с сервера на клиент.

Я думал о прослушивании входящих данных в цикле клиента, который я использую для отправки данных из очереди:

def run(self):
    while True:
        data = self.queue.get()
        logger.debug("Sending: %s", repr(data))
        data = cPickle.dumps(data)
        self.socket.write(data + "\r\n")
        # Here would be a good place to listen on the socket

Но есть несколько проблем с этим решением :

  • метод SSLSocket.read() является блокирующим
  • если в очереди нет данных, клиент никогда не получит никаких данных

Да, я мог бы использовать Queue.get_nowait() вместо Queue.get(), но, в целом, я думаю, что это не очень хорошее решение.

Вопрос

Есть ли хороший способ для достижения этих требований с помощью Twisted? У меня действительно нет таких навыков в Twisted, чтобы найти способ обойти это. Я даже не знаю, является ли использование LineReceiver хорошей идеей для такого рода проблем, потому что он не может отправлять какие-либо данные, если он не получает данные от клиента. Существует только lineReceived событие.

Может ли Twisted (или более общий любой управляемый событиями фреймворк ) решить эту проблему? У меня даже нет реального события на стороне связи. Если сервер решит отправить данные, он сможет их отправить; не должно быть необходимости ждать какого-либо события на стороне связи, насколько это возможно.

Ответы [ 2 ]

2 голосов
/ 29 сентября 2010

"Я даже не знаю, является ли использование LineReceiver хорошей идеей для такого рода проблем, потому что он не может отправлять данные, если он не получает данные от клиента. Существует только lineReceivedсобытие. "

Вы можете отправлять данные с помощью protocol.transport.write из любой точки мира, а не только из lineReceived.

0 голосов
/ 22 сентября 2010

«Мне нужен способ отправки команд с сервера на клиент».

Не делай этого.Он инвертирует обычное значение «клиент» и «сервер».Клиенты берут на себя активную роль и отправляют материал или запрашивают материал с сервера.

Способна ли Twisted (или, в более общем смысле, любая управляемая событиями среда) решить эту проблему?

Не должно.Вы инвертируете роль клиента и сервера.

Если сервер решает отправить данные, он должен быть в состоянии отправить их;

На самом деле неверно.

Сервер вынужден ждать, когда клиенты запросят данные.Это общепринятое значение «клиент» и «сервер».


"Один для отправки команд клиенту и один для передачи результатов на сервер. Звучит ли это решение какстандартная связь клиент-сервер для вас? "

Нет.

Если бы клиент отправлял сообщения на сервер и получал ответы от сервера, он соответствовал бы более обычным определениям.

Иногда такого рода вещи описываются как наличие «Агентов», каждый из которых является своего рода сервером, и «Контроллер», который является единым клиентом для всех этих серверов.

Контроллер отправляет работу агентам.Агенты являются серверами - они прослушивают порт, принимают работу от контроллера и выполняют работу.Каждый агент должен выполнять две одновременные операции (обычно через select API):

  • Отслеживать известный сокет, на котором он будет получать работу от единственного клиента.

  • Выполните работу (в фоновом режиме).

Это то, что обычно означает клиент-сервер.

Если каждыйАгент - это сервер, вы найдете множество библиотек, поддерживающих это.Это то, как все это делают.

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