Нужно ли мне 2 гнезда для этой настройки или один подойдет? - PullRequest
0 голосов
/ 11 ноября 2018

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

У клиента есть API для создания, объединения комнат и т. Д. На стороне сервера. Все эти вызовы API для сервера ожидают ответа от сервера, полученного в формате json.

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

Я предполагаю, что это невозможно сделать с одним сокетом, и мне понадобится как минимум 2 из них:

  • один сокет для вызовов API (поскольку он уже использует чтение / запись в сокете) для запроса и ответа
  • одна розетка для получения уведомлений

Мои вопросы:

  1. есть ли способ сделать это с одним сокетом разумным способом? или
  2. обязательно использовать как минимум 2 сокета в этой настройке?

Ответы [ 2 ]

0 голосов
/ 11 ноября 2018

Достаточно, чтобы клиент выделил только один сокет (и подключил одно TCP-соединение), при условии, что у вас есть четко определенный протокол обмена сообщениями между вашим клиентом и сервером.

В частности, я подозреваю, что вы ощущаете потребность во втором соединении с сокетом TCP в первую очередь потому, что вы не уверены в том, как решение с одним сокетом сможет обрабатывать несколько различных видов операций (например, вызовы RPC и асинхронных уведомлений) правильно, без одного типа операций, мешающего функционированию другого.

В чисто схеме передачи сообщений обработка всего через один сокет проста - когда ваш клиент хочет отправить сообщение на сервер, он вызывает вашу функцию SendMessage() (или как вы ее называете), и ваш код ставит в очередь байты для отправки через сокет; и наоборот, когда сервер отправляет сообщение вашему клиенту, ваш код ввода-вывода получает байты, и, если все байты сообщения были получены, он анализирует их и вызывает соответствующую функцию обратного вызова (MessageReceived() или что-то еще) реагировать на них соответствующим образом. Поскольку ваш клиент никогда нигде не блокируется (за исключением, возможно, некоторых вызовов типа WaitForNextEvent(), таких как select() или poll()), интеграция нескольких одновременных задач не является проблемой.

В общем, я рекомендую не использовать семантику в стиле RPC (т. Е. Когда ваш клиентский код вызывает вызов функции, которая скрывает сетевую операцию, а вызов функции не возвращается до тех пор, пока ответ не будет получен обратно с сервера), потому что он оставляет вашего клиента во власти сервера и подключения к сети - в частности, он заставит ваш клиентский поток зависать (блокироваться при вызове RPC) всякий раз, когда происходит временное отключение сети, что не очень хороший пользователь опыт.

Тем не менее, если вы должны использовать семантику в стиле RPC, асинхронные уведомления все еще возможны только с одним сокетом; вам просто нужно включить код в ваши RPC-функции, который дает им возможность вызывать соответствующую функцию обратного вызова (т. е. SomeAsynchronousEventOccured() или как вы хотите ее вызывать), когда они получают сообщение об асинхронном событии, произошедшем из сокета. Обратите внимание, что это означает, что функция асинхронного обратного вызова может быть вызвана до того, как ваша RPC-функция вернет свой сетевой результат, что может быть немного удивительно для некоторых программистов, поэтому обязательно документируйте, что это возможно. (По крайней мере, он по-прежнему вызывается в том же потоке, поэтому условия гонки не будут проблемой, хотя могут возникнуть проблемы с повторным входом)

0 голосов
/ 11 ноября 2018

Вам нужно только одно соединение между сервером и каждым клиентом. Это соединение может передавать сообщения в обоих направлениях (вызовы API и уведомления).

Большинство API сокетов работают так: вы открываете порт на сервере, создавая сокет прослушивания. Каждый клиент, который подключается, становится другим сокетом. Этот сокет представляет соединение с этим клиентом. Скорее всего, вам нужно вести список всех подключенных клиентов. Там должен быть один сокет, связанный с открытым портом.

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