Моя программа использует объект NetworkOutput
, который можно использовать для записи данных на удаленный сервер. Семантика заключается в том, что в случае, если объект в данный момент подключен (поскольку существует удаленный сервер), данные фактически отправляются через сокет. В противном случае он молча отбрасывается. Некоторые наброски кода:
class NetworkOutput
{
public:
/* Constructs a NetworkOutput object; this constructor should not block, but it
* should start attempting to the given host/port in the background.
*
* In case the connection gets closed for some reason, the object should immediately
* try reconnecting.
*/
NetworkOutput( const std::string &hostName, unsigned short port );
/* Tells whether there is a remote client connected to this NetworkOutput object.
* Clients can use this function to determine whether they need to both serializing
* any data at all before calling the write() function below.
*/
bool isConnected() const;
/* Write data to the remote client, if any. In case this object is not connected
* yet, the function should return immediately. Otherwise it should block until
* all data has been written.
*
* This function must be thread-safe.
*/
void write( const std::vector<char> &data );
};
Прямо сейчас у меня это реализовано с использованием неблокирующих сокетов. В конструкторе NetworkOutput
я создаю сокет TCP, а также внутреннее вспомогательное окно. Затем я выполняю WSAAsyncSelect вызов на сокете. Это делает сокет неблокирующим, и это заставит сообщение волшебного окна (которое я зарегистрировал самостоятельно) отправлять во внутреннее вспомогательное окно в случае, если какое-либо интересное событие (такое как «соединение установлено» или «соединение закрыто») происходит в сокете , Наконец, я запускаю попытку подключения, используя WSAConnect . Это немедленно возвращается, и оконная процедура моего внутреннего вспомогательного окна получит уведомление, как только соединение установится успешно. Если соединение закрыто (потому что удаленный клиент ушел), будет вызвана процедура сообщения, и я попытаюсь восстановить соединение.
Эта система позволяет мне подключать и отключать удаленного клиента по желанию. Это работает довольно хорошо, но, к сожалению, это требует, чтобы у меня был запущен цикл сообщений. Без цикла сообщений уведомления, отправленные вызовом WSAAsyncSelect , по-видимому, не приходят в мое окно помощника.
Есть ли способ реализовать класс, как описано выше, не требуя цикла сообщений? Я возился с использованием блокирующих сокетов в потоке помощников, но пока не мог придумать ничего разумного. Я также подумал об использовании сокета UDP, чтобы мне вообще не нужно было подключаться, но я хотел бы знать, прослушивает ли удаленный клиент, чтобы в случае наличия нет удаленного клиента клиентам класса NetworkOutput
не нужно выполнять сериализацию сложных объектов, прежде чем они смогут вызвать write()
.