Асинхронная многонаправленная связь между сервером и клиентом через один и тот же открытый сокет?
Вопрос
У меня есть клиент-серверное приложение, в котором клиент находится на устройстве Windows Mobile 6, написанном на C++, а сервер — на полной версии Windows и написан на C#.
Первоначально мне это было нужно только для отправки сообщений от клиента на сервер, при этом сервер только когда-либо отправлял обратно подтверждение о том, что он получил сообщение.Теперь я хотел бы обновить его, чтобы сервер мог отправлять клиенту сообщение для запроса данных.Поскольку в настоящее время я настроил его так, что клиент находится в режиме приема только после отправки данных на сервер, это не позволяет серверу отправлять запрос в любое время.Мне пришлось бы ждать данных клиента.Моей первой мыслью было бы создать на клиенте еще один поток с отдельным открытым сокетом, прослушивающим запросы сервера... точно так же, как сервер уже сделал это в отношении клиента.Есть ли способ в одном потоке и с использованием одного и того же сокета всем серверам отправлять запросы в любое время?
Можете ли вы использовать что-нибудь для эффекта WaitForMultipleObjects()
и передать ему буфер приема и событие, сообщающее, что есть данные для отправки?
Решение
Когда мне нужно было написать приложение с моделью клиент-сервер, где клиенты могли бы выходить и входить, когда захотят (я предполагаю, что это также относится и к вашему приложению, поскольку вы используете мобильные устройства), я позаботился о том, чтобы клиенты отправляли В сети сообщение на сервер, указывающее, что они подключены и готовы делать все, что им нужно.
в это время сервер мог отправлять сообщения обратно клиенту через то же открытое соединение.
Кроме того, но я не знаю, применимо ли это к вам, у меня было что-то вроде сердцебиение клиенты отправляли данные на сервер, сообщая ему, что он все еще онлайн.Таким образом, сервер узнает, когда клиент был принудительно отключен от сети, и может снова пометить этого клиента как отключенного от сети.
Другие советы
Использование асинхронной связи вполне возможно в одном потоке!
В разработке сетевого программного обеспечения существует общий шаблон проектирования, называемый шаблоном реактора (посмотри на эту книгу).Некоторые известные сетевые библиотеки предоставляют реализацию этого шаблона (посмотри на ЭЙС).
Если кратко, то реактор — это объект, вы прописываете внутри все свои сокеты и чего-то ждете.Если что-то случилось (поступили новые данные, разорвалось соединение...) реактор вас оповестит.И, конечно же, вы можете использовать только один сокет для асинхронной отправки и получения данных.
Мне неясно, хотите ли вы добавить асинхронные биты на сервер на C# или на клиент на C++.
Если вы говорите об этом на C++, настольные платформы Windows могут выполнять сокетный ввод-вывод асинхронно через API, использующие перекрывающийся ввод-вывод.Для сокетов WSASend и WSARecv допускают асинхронный ввод-вывод (прочитайте документацию по их параметрам LPOVERLAPPED, которые вы можете заполнить событиями, которые устанавливаются после завершения ввода-вывода).
Я не знаю, поддерживают ли платформы Windows Mobile эти функции, поэтому вам, возможно, придется покопаться дополнительно.
Проверить Азио.Это перекрестно-совместимая библиотека C++ для асинхронного ввода-вывода.Я не уверен, будет ли это полезно для сервера (я никогда не пытался связать стандартную DLL C++ с проектом C#), но для клиента это было бы полезно.
Мы используем его в нашем приложении, и он решил большинство наших проблем с параллелизмом ввода-вывода.