Долгоживущий многопоточный клиент для проприетарного протокола (Python, select, epoll) - PullRequest
2 голосов
/ 24 февраля 2012

Во-первых, я давно скрываюсь, но в первый раз я хочу поблагодарить вас всех за создание сайта!

Я нахожусь в ситуации, когда мне нужно реализовать клиентскую часть проприетарного протокола. Протокол использует TCP / IP внизу, и поток сообщений можно обобщить следующим образом:

  1. Клиент подключается к серверу
  2. Клиент проявляет интерес к данным определенного типа
  3. Если у сервера есть такие данные, они отправляются клиенту
  4. Клиент подтверждает прием на сервер
  5. Клиенту теперь нужно сообщить серверу, что он все еще интересуется данными того же типа
  6. Сервер отправляет данные клиенту по мере поступления
  7. Клиент должен время от времени отправлять на сервер запросы поддержки активности на уровне приложения (например, каждую минуту или около того)
  8. Некоторые сообщения с сервера требуют, чтобы клиент отправил ответ обратно на сервер
  9. Клиент отключается

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

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

Я хорошо осведомлен о GIL, поэтому я думаю, что это не имеет смысла комментировать это, я только пишу клиент, я не могу изменить какие-либо другие части архитектуры.

Так что дело в том, что мне никогда не приходилось копаться ниже уровня HTTP, мне посчастливилось всегда использовать некоторые уже существующие библиотеки, а с другой стороны, я не так много занимался сетевым программированием, что в первый раз я сам стану чем-то подобным.

Мне бы хотелось, чтобы у меня была возможность узнать больше обо всех асинхронных библиотеках / инструментах / инструментариях, таких как select, epoll, libev или gevent.

Проблема в том, что большинство ресурсов в сети имеют дело с серверами записи, и я даже не уверен, что развертывание клиента на многопоточном означает, что не все они будут делать много. Все серверы, очевидно, являются однопоточными, но не ясно, потому что не нужны несколько потоков или потому, что такие вещи, как epoll, на самом деле не любят, когда их используют несколько потоков.

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

Что вы думаете обо всем этом? Являются ли асинхронные библиотеки хорошим выбором в этом случае? Можете ли вы вспомнить примеры кода, на которые я мог бы взглянуть? Я использую Python, но я думаю, что вопрос достаточно общий, чтобы я мог использовать C, C ++ или Java для вдохновения.

Большое, большое спасибо!

1 Ответ

0 голосов
/ 02 марта 2012

Возможно ли каждому потоку (каждому клиенту) открыть свой сокет?В этом случае все это не проблема: только клиент в этом одном потоке имеет дескриптор этого сокета, и поэтому он автоматически получает правильные данные с сервера.Для сервера все эти подключения от клиента будут выглядеть как полностью независимые клиентские подключения (и это именно то, что они есть).

Если одним из требований является ограничение общего количества сетевых подключений, вы можетесоздать специальный поток, который поддерживает соединение с сервером и который локально получает запросы на связь от различных потоков / Но использование независимых сокетов (по одному на поток), вероятно, намного проще.уровень поддержки активности?Поскольку TCP может сделать это для вас, автоматически.Если подтверждение активности не получено вовремя, сокет закрывается, таким образом информируя другую сторону, что время соединения истекло.Рассматривайте это как вариант, если это возможно в вашем случае.

Наконец, если вам не нужно выполнять поддержку активности на уровне приложения, вы можете воспользоваться одним из приятных аспектов многопоточного программирования.Разрабатывайте каждый поток так, как если бы он был единственным, и вам вообще не нужно беспокоиться ни о чем асинхронном.Например, вы можете написать своему клиенту, чтобы он отправил запрос, а затем заблокировать ожидание резонанса, выполнить вычисления и либо отправить результат, либо проверить, поступило ли больше данных с сервера.Данные с сервера будут накапливаться в окне приема TCP на вашей стороне.Это также служит средством управления потоком: если ваш клиент становится слишком медленным и окно приема заполнено, то сервер больше не может отправлять.Это может заблокировать сервер, поэтому вам нужно посмотреть, сможет ли сервер справиться с этой ситуацией.

...