Пишу новый сервер на IOCP. В потоке приёма новых подключений вызываю WSARecv
(после успешного accept
естественно). Срабатывает WSARecv
с 3-5 попытки для клиента на C++, для браузера вообще ни разу не срабатывало (подключается по WebSocket). Причина всегда одна и та же - результат 6 после вызова WSAGetLastError()
.
Лог сервера выглядит примерно так (большие значения transferred
не понятно откуда, актуальная информация в Received XX bytes from ...
и Sent XX bytes to ...
):
To stop server press ESC
Client 324 added (IP 127.0.0.1)
Recv
error 6 on socket 324
Client 328 added (IP 127.0.0.1)
Recv
error 6 on socket 328
Client 332 added (IP 127.0.0.1)
Recv
error 6 on socket 332
Client 336 added (IP 127.0.0.1)
Thread 8
completed operation for client 336 (IP 127.0.0.1), transferred
62323228 bytes
Received 25 bytes from 336
Thread 7 completed
operation for client 336 (IP 127.0.0.1), transferred 59963932
bytes
Sent 1 bytes to 336
Thread 8 completed operation for
client 336 (IP 127.0.0.1), transferred 62323228 bytes
Received 11
bytes from 336
Thread 7 completed operation for client 336 (IP
127.0.0.1), transferred 59963932 bytes
Sent 1 bytes to 336
Thread 7 completed operation for client 336 (IP 127.0.0.1),
transferred 59963932 bytes
Client 356 added (IP 127.0.0.1)
Thread 7 completed operation for client 356 (IP 127.0.0.1),
transferred 59963932 bytes
Received 533 bytes from 356
Thread
8 completed operation for client 356 (IP 127.0.0.1), transferred
62323228 bytes
Sent 129 bytes to 356
Thread 8 completed
operation for client 356 (IP 127.0.0.1), transferred 62323228
bytes
Client 360 added (IP 127.0.0.1)
Recv error 6 on socket
360
Client 364 added (IP 127.0.0.1)
Recv error 6 on socket
364
Client 368 added (IP 127.0.0.1)
Recv error 6 on socket
368
Client 372 added (IP 127.0.0.1)
Первые три попытки проводил один и тот же клиент. На четвёртый раз пошёл обмен. Последние неудачные попытки были от браузера - он вообще не смог подключиться.
Код принимающего потока:
unsigned int __stdcall AcceptThread(void * param){
SOCKET ServerSocket = (SOCKET)param;
WSANETWORKEVENTS WSAEvents;
while(WAIT_OBJECT_0 != WaitForSingleObject(EventShutdown, 0)){
if( WSA_WAIT_TIMEOUT != WSAWaitForMultipleEvents(1, &EventAccept, FALSE, 100, FALSE) ){
WSAEnumNetworkEvents(ServerSocket, EventAccept, &WSAEvents);
if((WSAEvents.lNetworkEvents & FD_ACCEPT) && (0 == WSAEvents.iErrorCode[FD_ACCEPT_BIT])){
client *Client = new client();
int addrlen = sizeof(Client->address);
//Accept remote connection attempt from the client
if( INVALID_SOCKET == Client->Socket(accept(ServerSocket,(sockaddr*)&(Client->address),&addrlen)) ) delete Client;
else if( NULL != CreateIoCompletionPort((HANDLE)Client->Socket(), hIOCP, (DWORD)Client, 0) ){
AddClient(Client);
DWORD flag = 0;
// Init receiving
int result = WSARecv(Client->Socket(), Client->RecvContext(), 1, Client->Rcvd(), &flag, Client->Overlapped(), NULL);
int err = WSAGetLastError();
if((SOCKET_ERROR == result) && (WSA_IO_PENDING != err)){
printf("Recv error %d on socket %d\n", err, Client->Socket());
}
}
}
}
}
printf("AcceptThread closed\n");
return 0;
}
С чем эта ошибка может быть связанна? Почему WSA_INVALID_HANDLE
, и из-за какой магии это пропадает с n-ной попытки подключения?
PS: вся необходимая инициализация выполняется до создания потока с AcceptThread
. Если бы не создался порт завершения или была ошибка при WSACreateEvent
или WSAEventSelect
на подготовленном принимающем сокете, до потока приёма дело бы не дошло.
Ох и Microsoft... Оказывается эта ошибка, WSA_INVALID_HANDLE
, касается поля hEvent
структуры OVERLAPPED
.
Из MSDN
A handle to the event that will be set to a signaled state by the system when the operation has completed. The user must initialize this member either to zero or a valid event handle using the CreateEvent function before passing this structure to any overlapped functions
Я вот всегда, когда пишу свои структуры и классы, в их конструкторах инициализирую поля-указатели nullptr
-ом. В WinAPI такие "мелочи" решили оставить на
user must
))
Виртуальный выделенный сервер (VDS) становится отличным выбором
Есть такая задача: пройтись по хэдэр файлу и записать в список все методы класса, определенные в хэдэре, при этом отделить чистые виртуальные,...
В теме еще разбираюсь плохо так что прошу строго не судить
Почему эта программа выводит doubledouble, я же явно указываю int?!
Пытаюсь разобраться с wmi, использую последний снипет из статьи Calling a Provider Method Не могу понять как указать ProcessStartupInformation для Win32_ProcessCreate на примере...