Асинхронная разнонаправленная связь сервер-клиент через один и тот же открытый сокет?

У меня есть клиент-серверное приложение, в котором клиент находится на устройстве Windows Mobile 6, написано на C++, а сервер работает на полной Windows и написан на C#.

Изначально мне это было нужно только для отправки сообщений от клиента на сервер, а сервер только когда-либо отправлял обратно подтверждение того, что он получил сообщение. Теперь я хотел бы обновить его, чтобы сервер действительно мог отправлять сообщение клиенту для запроса данных. Поскольку у меня в настоящее время он настроен так, что клиент находится в режиме приема только после того, как он отправляет данные на сервер, это не позволяет серверу отправлять запрос в любое время. Придется ждать данных клиента. Моя первая мысль заключалась в том, чтобы создать еще один поток на клиенте с отдельным открытым сокетом, прислушиваясь к запросам сервера ... точно так же, как сервер уже относится к клиенту. Есть ли способ в одном потоке и с использованием одного и того же сокета для всего сервера отправлять запросы в любое время?

Можете ли вы использовать что-то для эффекта WaitForMultipleObjects() и передать ему буфер приема и событие, которое сообщает ему, что есть данные для отправки?

Ответов (4)

Решение

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

в то время сервер мог отправлять сообщения обратно клиенту через то же открытое соединение.

Кроме того, но я не знаю, применимо ли это к вам, у меня было какое-то сердцебиение, которое клиенты отправляли на сервер, давая ему знать, что он все еще в сети. Таким образом, сервер знает, когда клиент был принудительно отключен от сети, и может пометить этого клиента как отключенного.

Я не понимаю, хотите ли вы добавить асинхронные биты к серверу на C# или к клиенту на C++.

Если вы говорите об этом на C++, настольные платформы Windows могут выполнять ввод-вывод сокетов асинхронно через API, которые используют перекрывающийся ввод-вывод. Для сокетов WSASend и WSARecv допускают асинхронный ввод-вывод (прочтите документацию по их параметрам LPOVERLAPPED, которые вы можете заполнить событиями, которые устанавливаются по завершении ввода-вывода).

Я не знаю, поддерживают ли платформы Windows Mobile эти функции, поэтому вам, возможно, придется потратить немного больше времени.

Проверьте asio . Это кросс-совместимая библиотека C++ для асинхронного ввода-вывода. Я не уверен, будет ли это полезно для сервера (я никогда не пытался связать стандартную DLL c ++ с проектом c #), но для клиента это было бы полезно.

Мы используем его в нашем приложении, и он решил большинство наших проблем параллелизма ввода-вывода.

Использование асинхронной связи полностью возможно в одном потоке!

В разработке сетевого программного обеспечения существует общий шаблон проектирования, называемый шаблоном реактора (см. Эту книгу ). Некоторые известные сетевые библиотеки предоставляют реализацию этого шаблона (см. ACE ).

Если коротко, то реактор - это объект, вы прописываете внутри все свои сокеты и чего-то ждете. Если что-то случилось (поступили новые данные, соединение закрылось ...), реактор уведомит вас. И, конечно же, вы можете использовать только один сокет для асинхронной отправки и получения данных.