Click here to Skip to main content
15,888,527 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hey there,

I'm having some troubles with IOCP and receiving packets. First, here's the basics of what I do in my server socket class to accept connections:

CreateIoCompletionPort for the server socket, then initialize worker threads. WSACreateEvent(), then WSAEventSelect using the server socket, accept event, and the FD_ACCEPT definition. CreateThread to start the accept thread. In the accept thread, WSAWaitForMultipleEvents using accept event handle and socket. Reset the socket event using WSAEnumNetworkEvents. Obtain the client remote socket using WSAAccept. CreateIoCompletionPort for the client socket using the client socket, server's iocp handle, and client context.

What's expected is that I can then get the first packet receive (using WSARecv) after calling GetQueuedCompletionStatus (used with the server's iocp handle), but the server cannot get past GetQueuedCompletionStatus. I feel that I should be telling the server some how that I want to receive packets now, but I'm not sure how to do that.

Any tips would be a huge help. Thanks in advance.

Edit: Here's the code from the Accept Thread:
C++
sockaddr_in clientIpAddress;
int addressLength = sizeof(clientIpAddress);

// Accept the client connection and get the remote socket from the client:
SOCKET clientSocket = WSAAccept(_wsaSocket, (sockaddr*)&clientIpAddress, &addressLength, NULL, NULL);
cout << "<DEBUG> Incoming Connection from " << inet_ntoa(clientIpAddress.sin_addr) << endl;
if (clientSocket == INVALID_SOCKET) 
{ 
	printf("WSAAccept failed: %d\n", WSAGetLastError()); 
	closesocket(clientSocket);
	return;
}

// Create the client class to encapsulate the client socket:
Client client(clientSocket, &clientIpAddress);
if (CreateIoCompletionPort((HANDLE)clientSocket, _iocpHandle, (DWORD)&client, 0) == NULL)
{ 
	printf("CreateIoCompletionPort failed: %d\n", WSAGetLastError()); 
        closesocket(clientSocket);
	return;
}


And here's the code from the Worker Thread:
C++
// Attempt to dequeue an I/O completion packet from the server's I/O completion port. If there is no 
// completion packet queued, wait for a pending I/O operation associated with the completion port to 
// complete. 
if (!GetQueuedCompletionStatus(server->GetIOCPHandle(), &bytesTransferred, 
	(LPDWORD)&clientPtr, &overlappedPtr, INFINITE))
{ printf("GetQueuedCompletionStatus failed: %d\n", GetLastError()); continue; }

cout << "<DEBUG> Test Point Hit.\n";
// If the client passed in the completion status is null, the socket system is shutting down. Else, retrieve
// the client from the client pointer (void pointer to client pointer).
if (clientPtr == NULL) break;
Client* client = (Client*)clientPtr;


If I put the WSARecv in the accept thread, it will make GetQueuedCompletionStatus work, but I can't have the initial receive in the accept thread for my application. Thanks again for your time.
Posted
Updated 26-Jul-13 15:12pm
v3

Without the actual code and more info about environment it is very difficult to guess what is happening.

Are you starting with the event non-signalled? In some cases the program logic will cause the thread to block because of this.

If using Windows 8 this may apply
http://stackoverflow.com/questions/12047960/getqueuedcompletionstatus-cant-dequeue-io-from-iocp-if-the-thread-which-origina[^]

Suggest also you look at this article:

A simple application using I/O Completion Ports and WinSock[^]

Again your code is the key.
 
Share this answer
 
v4
The problem was that I was missing the initial receive. The initial recv is what gets queued for packet processing in IOCP. After telling the socket to receive data, it worked perfectly. Thanks for the tips, hopefully this helps anyone who gets this far.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900