IOCP WSARecv всегда возвращает ошибку 10022

Я использую IOCP на Windows. Ранее я использовал метод GetQueuedCompletionStatus опросить очередь и все было хорошо. Но когда я решил реорганизовать логику таким образом, чтобы использовать процедуру завершения с WSARecv вызвать это всегда терпит неудачу с ошибкой WSAEINVAL (10022). Этот код в потоке создан с CreateTread

int flags = 0;
m_iocport = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
handle = CreateIoCompletionPort(clientSocket, m_iocport, 0, 0);
OVERLAPPED_EX *over = new OVERLAPPED_EX();
result = WSARecv(clientSocket, &over->m_wsabuf, 1, NULL, &flags, over, WorkerRoutine);

А рабочая подпрограмма пуста и имеет следующее определение:

void static CALLBACK WorkerRoutine(DWORD Error, DWORD BytesTransferred, LPWSAOVERLAPPED Overlapped, DWORD InFlags) {}

Когда я прохожу NULL вместо WorkerRoutine к методу WSARecv все работает нормально. Но когда я передаю процедуру завершения вызова, она завершается с ошибкой 10022. Я пытался использовать WorkerRoutine а также &WorkerRoutine ничего не помогает

hEvent свойство установлено в NULL в объекте OVERLAPPED_EX.

0

Решение

порт завершения ввода / вывода, связанный с файлом и lpCompletionRoutine это взаимоисключающие параметры. Вы не можете использовать его одновременно. когда вы делаете это — ядро ​​возвращает STATUS_INVALID_PARAMETER который переводится на WSAEINVAL, так ты и должен получить именно эту ошибку.

IOCP и ApcRoutine 2 разными способами уведомляют вас о завершении операции. при использовании IOCP — система отправляет пакет в IOCP по завершении. вам нужно использовать GetQueuedCompletionStatus или же NtRemoveIoCompletion извлечь этот пакет позже. и это не «опрос». с другой стороны, если вы используете ApcRoutine Системная вставка apc в вашу ветку. использовать два способа уведомления одновременно и одновременно — это логическая ошибка и правильное выполнение ядра при возврате к вам STATUS_INVALID_PARAMETER в этом случае.

к сожалению, это не ясно указано в MSDN или как минимум, я не могу найти это. но некоторые исследования + исходный код WRK помогают понять эту ситуацию:

WSARecv внутренний звонок ZwDeviceIoControlFile и как результат в ядре называется IopXxxControlFile. когда lpCompletionRoutine != 0 ApcRoutine параметр для IopXxxControlFile присутствует, и вы терпите неудачу именно в этот пункт:

    //
// If this file has an I/O completion port associated w/it, then ensure
// that the caller did not supply an APC routine, as the two are mutually
// exclusive methods for I/O completion notification.
//

if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) {
ObDereferenceObject( fileObject );
return STATUS_INVALID_PARAMETER;
}

также вы можете разместить m_wsabuf в стеке. допустимым должен быть только буфер до какой точки WSABUF

Если эта функция выполняется в наложенном виде, это
Обязанность поставщика услуг Winsock захватить WSABUF
структуры, прежде чем вернуться из этого вызова. Это позволяет приложениям
строить на основе стека WSABUF массивы, на которые указывает lpBuffers
параметр.

так что вы можете разместить OVERLAPPED_EX единственный буфер до какой точки WSABUF.buf но не целый WSABUF, но это уже не связано с вашей ошибкой

2

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

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

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