Windows — WSARecv иногда возвращает «неверный дескриптор (ошибка № 6)» для сокета, связанного с портом IOCP. (C ++)

Я пытаюсь написать сервер, который может поддерживать множество клиентских подключений одновременно, поэтому я пытаюсь сделать это с IOCP. Итак, позвольте мне кратко рассказать о моем потоке кода, и тогда я смогу объяснить свою проблему. Прежде всего, сервер открывает порт для прослушивания и ожидания вызова «принять» для новых входящих соединений. Для справки я использовал тот же код, что и упомянутый Вот Таким образом, он принимает каждое новое входящее соединение и возвращает новый дескриптор сокета (sd), а затем помечает как неблокирующий с помощью:

arg = 1;
ioctlsocket(sd, FIONBIO, &arg);

и затем включите TCP_NODELAY:

level = IPPROTO_TCP;
optName = TCP_NODELAY;
value = 1;
setsockopt(sd, level, optName, (const char*)&value, sizeof(value));

после этого связывается с портом IOCP как:

CreateIoCompletionPort((HANDLE)sd, iocp_port, (DWORD)completion_key, 4);

завершение_ключа — это объект класса, который является не чем иным, как контейнером, он содержит буфер данных, буфер перекрытия, тип запроса recv / send и т. д.
и в последнем издании вызов для чтения:

WSARecv(sd, wsabuf, 1, &bytes, &flags, overlapped, NULL);

wsabuf и overlapped являются частью объекта дополнения_ключа.

В 90% случаев он работает нормально, то есть когда есть некоторые входящие данные, доступные на этом сокете, «GetQueuedCompletionStatus» разблокируется и у него есть действительные данные. Но иногда вызов WSARecv возвращается с ошибкой, а GetLastError () возвращает 6, что является ошибкой «неверного дескриптора». Я немного сбит с толку, почему так происходит.

То, как я создаю порт iocp:

iocp_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);

и есть потоки, которые ожидают на «GetQueuedCompletionStatus».

2

Решение

Я отслеживал все системные вызовы, которые происходили в фоновом режиме. WSARecv внутренне вызывает NtDeviceIoControlFile, и существует аргумент «Событие», который совпадает с тем, что передается в структуре lpOverlapped WSARecv как hEvent. Я не устанавливал hEvent в NULL, поэтому он принимал какое-то мусорное значение, когда он был NULL, тогда NtDeviceIoControlFile возвращался успешно, а для других случаев он возвращал ошибку «INVALID_HANDLE». К сожалению, большую часть времени это было NULL.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]