Веб-сокеты Poco C++ - как использовать неблокирующим образом?

Я использую библиотеки Poco C++ для настройки сервера веб-сокетов, к которому клиенты могут подключаться и передавать некоторые данные на свой веб-интерфейс. Итак, у меня есть цикл, который постоянно отправляет данные, и я также хочу слушать, закрывают ли клиенты соединение с помощью функции receiveFrame(), в остальном клиент полностью пассивен и не отправляет никаких данных или чего-либо еще. Проблема в том, что receiveFrame() блокирует соединение, а это не то, что мне нужно. В основном я хочу проверить, не вызвал ли клиент функцию javascript close() и остановить потоковую передачу данных, если это так. я пытался использовать

ws.setBlocking(false);

Но теперь ReceiveFrame выдает исключение каждый раз, когда вызывается. Я также попытался полностью удалить receiveFrame, который работает, если соединение прерывается закрытием браузера, но если клиент вызывает функцию close(), сервер все равно пытается отправить данные клиенту. Итак, как я могу осуществить это? Есть ли способ проверить, есть ли клиентские кадры, которые нужно получить, и если нет, то просто продолжить?


person SilverTear    schedule 16.10.2014    source источник


Ответы (2)


Вы можете многократно вызывать Socket::select() (с тайм-аутом) в отдельном потоке; когда вы обнаружите читаемый сокет, вызовите receiveFrame(). Несмотря на вводящее в заблуждение название, вызов Socket::select() оборачивает epoll() или poll() на платформах, где они доступны.

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

person Alex    schedule 17.10.2014
comment
Select() действительно делает то, чего я хочу добиться, спасибо! - person SilverTear; 17.10.2014

setBlocking() не делает того, что вы ожидаете. Вот небольшая информация об этом: http://www.scottklement.com/rpg/socktut/nonblocking.html

Что вы, вероятно, захотите сделать, так это использовать setReceiveTimeout() в своем сокете, чтобы контролировать, как долго он будет ждать, прежде чем вернуть вам управление. Затем проверьте свой ответ и зациклите все, если это необходимо. Документы Poco содержат больше информации о том, как использовать эту часть API. Просто поищите WebSockets.

person Unix-Ninja    schedule 16.10.2014
comment
Когда я использую ws.setReceiveTimeout(Poco::Timespan(0, 500)); установить тайм-аут на 500 микросекунд, он все еще блокируется. Когда я устанавливаю ws.setReceiveTimeout(Poco::Timespan(1, 0)); receiveFrame выдает исключение тайм-аута и закрывает соединение, что нехорошо. - person SilverTear; 16.10.2014
comment
Хм, я не уверен, что это будет работать для WebSockets, но с обычными сокетами я использую класс Poco SocketReactor и определяю обработчик. Когда соединение закрывается, это вызывает завершение класса, где я могу просто поместить всю свою очистку в деконструктор. Поскольку SocketReactor автоматически порождает новый поток, все остальное может выполняться по мере необходимости, не блокируя получение сокетов. В худшем случае вы можете создать поток самостоятельно и просто заблокировать этот поток с помощью receiveFrame(). - person Unix-Ninja; 16.10.2014