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 - ваш друг