Обработка асинхронных сокетов в WinSock? - PullRequest
4 голосов
/ 18 февраля 2011

Я использую окно сообщения и WSAAsyncSelect.Как я могу отслеживать несколько сокетов (клиентов) с одним окном сообщения?

Ответы [ 2 ]

12 голосов
/ 18 февраля 2011

Windows Поддерживает несколько режимов работы сокетов, и вам необходимо уточнить, какой из них вы используете:

  • Блокировка розеток. Блок отправки и получения.
  • Неблокирующие сокеты: send и recv возвращают E_WOULDBLOCK, а select () используется для определения, какие сокеты готовы
  • Асинхронные сокеты: WSAAsyncSelect - сокеты публикуют уведомления о событиях в HWND.
  • EventSockets: WSAEventSelect - сокеты сигнализируют о событиях.
  • Перекрывающиеся сокеты: WSASend и WSARecv используются с сокетами, передавая структуры OVERLAPPED. Перекрывающиеся сокеты могут быть объединены с портами IOCompletion и обеспечивают лучшую масштабируемость.

С точки зрения удобства асинхронные сокеты просты и поддерживаются классом MFC CAsyncSocket.

Сокеты событий сложно использовать, поскольку максимальное число объектов, передаваемых в WaitForMultipleObjects, равно 64.

Перекрывающиеся сокеты с IO CompletionPorts являются наиболее масштабируемым способом обработки сокетов и позволяют масштабировать серверы на базе Windows до десятков тысяч сокетов.


По моему опыту, при использовании Async Sockets на ум приходят следующие вещи:

  • Обработка событий FD через оконные сообщения может обрабатывать «много» сокетов, но производительность начнет снижаться, поскольку вся обработка событий выполняется в одном потоке, сериализованном через очередь сообщений, которая может быть также занята обработкой событий пользовательского интерфейса. если используется в однопоточном приложении с графическим интерфейсом.

  • Если вы размещаете окна или таймеры графического интерфейса пользователя в одном потоке с большим количеством сокетов: сообщения WM_TIMER и WM_PAINT имеют низкий приоритет и будут генерироваться, только если очередь сообщений пуста. Таким образом, очень занятые сокеты могут привести к сбою графического интерфейса или к сбою синхронизации на основе SetTimer.

  • Создание выделенного рабочего потока для обработки ваших сокетов, если хостинг GUI решает эти проблемы. Учитывая, что в рабочем потоке будет цикл сообщений, вы можете использовать очередь сообщений для обмена сообщениями между потоками - просто отправляйте сообщения WM_APP в поток.

  • Самый простой способ сопоставить обратные вызовы FD с вашими объектами сокетов - создать массив объектов SocketObject для каждого HWND, который будет получать сообщения, а затем использовать индекс WM_USER + в качестве идентификатора сообщения каждый раз, когда вы вызываете WASAsyncSelect. Затем, когда вы получаете сообщения в диапазоне от WM_USER до WM_USER + (размер массива), вы можете быстро извлечь соответствующий объект состояния. WM_USER - 0x400, а WM_APP - 0x8000, поэтому вы можете индексировать до 31744 сокетов на окно сообщения, используя этот метод.

  • Не использовать массив статических областей. Вам необходимо связать массив с окном, так как вы можете создать сокеты в нескольких потоках. Каждой нити понадобится свой цикл сообщений и окно сообщений.

  • HWND_MESSAGE - ваш друг

0 голосов
/ 18 февраля 2011

Параметр wParam оконного сообщения, которое вы сообщаете WSAAsyncSelect() для отправки, будет указывать сокет, который вызвал сообщение.Это четко указано в документации WSAAsyncSelect() :

Когда в указанных сокетах происходит одно из назначенных сетевых событий, окно приложения hWnd получает сообщение wMsg.Параметр wParam определяет сокет, в котором произошло сетевое событие.Младшее слово lParam указывает на произошедшее сетевое событие.Старшее слово lParam содержит любой код ошибки.Код ошибки - любая ошибка, как определено в Winsock2.h.

...