Достающий задачу из порта завершения GetQueuedCompletionStatus - глючит?
Наблюдаю не совсем понятную для себя ситуацию:
1)Создаю порт завершения.
2)Создаю функцию обработки порта завершения.
3)Создаю сокет.
4)Связываю сокет с портом.
5)Вызываю WSASend и отправляю на удаленный сервер заведомо некорректное сообщение - просто "A".
Далее функция обработки ловит и достает из порта завершения с помощью GetQueuedCompletionStatus "сообщение" о готовой задаче, то есть мое сообщение в 1 байт отправилось:
//Условно:
void My_func_for_IOCP(...)
{
while (1)
{
my_BOOL_GetQueuedCompletionStatus = GetQueuedCompletionStatus(iocp, &my_DWORD, &my_CompletionKey, &my_WSAOVERLAPPED, INFINITE);
if (my_BOOL_GetQueuedCompletionStatus == TRUE)
{
std::cout << "my_DWORD:" << my_DWORD <<std::endl; //Выводится информация о том, сколько байт доступно для чтения/или сколько отправлено.
std::cout << std::endl << my_WSABUF_WSARecv.buf << std::endl;
my_WSARecv = WSARecv(my_SOCKET, &my_WSABUF_WSARecv, 1, NULL, &my_flag, &my_WSAOVERLAPPED_WSARecv, NULL);
}
}
После того, как задача из порта завершения была извлечена:
-вызываю функцию чтения WSARecv.
-После этого, в порт завершения должна поступить по мере готовности задача на чтение.
-Поэтому цикл while повторяется, соответвенно вызывается GetQueuedCompletionStatus и как в очереди появляется готовая задача - код выполнится далее...
-На консоль выводится информация о том, сколько байт доступно для чтения и я читаю из my_WSABUF_WSARecv..buf - кол-во байт соответвует действительности, сообщение от сервера такое:
HTTP/1.1 400 Bad Request Server: nginx Date: Thu, 08 Jul 2021 16:55:06 GMT Content-Type: text/html Content-Length: 166 Connection: close
400 Bad Request400 Bad Request
nginx
И вроде бы все хорошо, НО ситуация следующая: после того, как я прочитал пришедшее сообщение, в цикле вызывается опять функция WSARecv(это не правильно, просто так получилось) - и вот тут непонятки:
-Во первых судя по сообщению от сервера: Connection: close - сокет должен быть закрыт, НО функция WSARecv вызванная второй раз - не выдает ошибок, напротив она завершается успешно!
-И второе, WSARecv - завершилась успешно, цикл опять перешел к выполнению функции GetQueuedCompletionStatus и ТАМ откуда то была готовая задача!! Но при этом когда я смотрю, сколько байт готово по этой задаче:
std::cout << "my_DWORD:" << my_DWORD <<std::endl;
my_DWORD - показывает ноль.
Почему GetQueuedCompletionStatus - срабатывает ??? А не спит в ожидании ?
Ответы (1 шт):
Сервер может закрыть TCP-соединение на своей стороне двумя способами: послав TCP-пакет с флагом FIN (изящное закрытие) или с флагом RST (грубый сброс соединения). Если сокет прислал TCP-пакет с флагом FIN, то на уровне сокетов это будет выглядеть как завершение функций чтения (в т.ч. WSARecv) с результатом 0 байт. При использовании iocp GetQueuedCompletionStatus в такой ситуации возвращает true и 0 байт. Скорее всего, в Вашем случае происходит именно это. (Кстати, сокет при этом ещё жив. Послав FIN, сервер сообщает, что он больше ничего присылать не будет. Читать из сокета больше нельзя. Но чисто технически Вы можете в этот сокет писать, пока сами не отправили FIN или RST. Правда, если используется протокол HTTP с закрытием соединения после запроса, то писать в такой сокет бессмысленно. Сервер не будет читать. Поэтому такой сокет остаётся только закрыть.)