У меня есть клиент-серверное приложение, где клиент находится на устройстве Windows Mobile 6, написанном на C++, а сервер находится на полной Windows и написан на C#.
Изначально мне нужно было, чтобы оно только отправляло сообщения от клиента к серверу, а сервер лишь отправлял обратно подтверждение того, что он получил сообщение. Теперь я хотел бы обновить его так, чтобы сервер мог действительно отправлять сообщение клиенту для запроса данных. Поскольку в настоящее время я настроил его так, что клиент находится в режиме приема только после того, как отправит данные на сервер, это не позволяет серверу отправить запрос в любое время. Мне пришлось бы ждать данных от клиента. Моей первой мыслью было бы создать еще один поток на клиенте с отдельным открытым сокетом, прослушивающим запросы сервера... точно так же, как сервер уже имеет связь с клиентом. Есть ли способ, в рамках одного потока и используя один и тот же сокет, сделать так, чтобы сервер мог отправлять запросы в любое время?
Можете ли вы использовать что-то вроде WaitForMultipleObjects()
и передать ему буфер приема и событие, которое сообщит ему, что есть данные для отправки?
Когда мне нужно было написать приложение с клиент-серверной моделью, где клиенты могли выходить и входить, когда захотят (я предполагаю, что это также относится и к вашему приложению, поскольку вы используете мобильные устройства), я убедился, что клиенты посылают онлайн сообщение на сервер, указывая, что они подключены и готовы делать все, что им нужно.
В это время сервер мог отправлять сообщения обратно клиенту через то же самое открытое соединение.
Также, но я не знаю, применимо ли это для вас, у меня было что-то вроде сердечного ритма, который клиенты посылали серверу, давая ему знать, что они все еще онлайн. Таким образом, сервер знал, когда клиент был принудительно отключен от сети, и мог пометить его обратно как автономного.
Используя асинхронную коммуникацию полностью возможно в единственной нити!
Есть образец общего умысла в развитии сетевого программного обеспечения, названном реакторным образцом ([смотрят на эту книгу] [1]). Некоторая известная сетевая библиотека обеспечивает внедрение этого образца ([взгляд на ТУЗ] [2]).
Кратко, реактор - объект, Вы регистрируете все свои гнезда внутри, и Вы ждете чего-то. Если что-то произошло (новые данные прибыли, связь близко...), реактор уведомит Вас. И конечно, Вы можете использовать только одно гнездо, чтобы послать и полученные данные асинхронно.
[1]: http://www.amazon.fr/Pattern-Oriented-Software-Architecture-Concurrent-Networked/dp/0471606952/ref=sr_1_9? ie=UTF8& s=english-books& qid=1218980593& sr=1-9 [2]: http://www.cs.wustl.edu / ~ schmidt/ACE.html
Я не совсем понимаю, хотите ли вы добавить асинхронные биты к серверу на C# или к клиенту на C++.
Если вы говорите о том, чтобы сделать это на C++, то настольные платформы Windows могут выполнять асинхронный ввод/вывод сокетов через API, которые используют перекрытый ввод/вывод. Для сокетов, WSASend, WSARecv оба позволяют асинхронный ввод/вывод (читайте документацию по их параметрам LPOVERLAPPED, которые вы можете заполнить событиями, которые будут установлены, когда ввод/вывод завершится).
Я не знаю, поддерживают ли платформы Windows Mobile эти функции, так что вам, возможно, придется покопаться еще немного.
Посмотрите asio. Это кросс-совместимая библиотека c++ для асинхронного ввода-вывода. Я не уверен, будет ли это полезно для сервера (я никогда не пытался связать стандартную c++ DLL с c# проектом), но для клиента это было бы полезно.
Мы используем ее в нашем приложении, и это решило большинство наших проблем с параллелизмом ввода-вывода.