Sign in to follow this  
Ripiz

Failed IOCP attempt

Recommended Posts

Hello,

I've been reading through posts and noticed some people suggest to use IOCP on server to handle a lot packets more efficiently. I've used [url="http://askldjd.wordpress.com/2011/08/10/iocp-server-1-2-released/"]http://askldjd.wordp...r-1-2-released/[/url] as some kind of reference and tried to initialize basic IOCP and get it it working, however I get [i]WSA_INVALID_PARAMETER[/i] error in [i]GetQueuedCompletionStatus[/i] inside worker thread when client attempts to connect.

Here's my code:
[CODE]
void main() {
WSADATA wsaData;
int numThreads = 1;
vector<HANDLE> threads;

// InitializeWinsock();
WSAStartup(MAKEWORD(2,2), &wsaData);

// InitializeIocp();
m_ioCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, numThreads);
if(m_ioCompletionPort == NULL)
cout << "CreateIoCompletionPort() => " << WSAGetLastError() << endl;

// InitializeThreadPool();
threads.reserve(numThreads);
for(auto i = 0; i < numThreads; ++i)
threads.push_back(CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, m_ioCompletionPort, 0, 0));

// InitializeSocket();
InitializeSocket(ADDR_ANY, 50000);

// InitializeAcceptEvent();
m_socket = CreateOverlappedSocket();
PostAccept();

// client (?)
SOCKET client = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
sockaddr_in address = { };
address.sin_family = AF_INET;
address.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
address.sin_port = htons(50000);
auto result = WSAConnect(client, (sockaddr*)&address, sizeof(address), 0, 0, 0, 0);
if(result == SOCKET_ERROR)
cout << "WSAConnect() => " << WSAGetLastError() << endl;

system("pause");
}

void WorkerThread(HANDLE m_ioCompletionPort) {
for(;;) {
void *key = nullptr;
OVERLAPPED *overlapped = nullptr;
DWORD bytesTransferred = 0;

BOOL completionStatus = GetQueuedCompletionStatus(m_ioCompletionPort, &bytesTransferred, (LPDWORD)&key, &overlapped, INFINITE);

if(completionStatus == FALSE) {
cout << "GetQueuedCompletionStatus() => " << WSAGetLastError() << endl;
continue;
}

if(key == NULL) {
cout << "GetQueuedCompletionStatus() => " << WSAGetLastError() << endl;
break;
}
}
}

SOCKET CreateOverlappedSocket() {
return WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
}

LPFN_ACCEPTEX LoadAcceptEx(SOCKET s) {
LPFN_ACCEPTEX lpfnAcceptEx = NULL;
DWORD dwBytes = 0;
GUID GuidAcceptEx = WSAID_ACCEPTEX;

auto result = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidAcceptEx, sizeof(GuidAcceptEx), &lpfnAcceptEx, sizeof(lpfnAcceptEx), &dwBytes, NULL, NULL);
if(result == SOCKET_ERROR) {
cout << "WSAIoctl() => " << WSAGetLastError() << endl;
return nullptr;
}

return lpfnAcceptEx;
}

void AssociateDevice(HANDLE h) {
auto result = CreateIoCompletionPort(h, m_ioCompletionPort, 0, 0);
if(result == NULL) {
cout << "CreateIoCompletionPort() => " << WSAGetLastError() << endl;
return;
}
}

void InitializeSocket(uint32 addressToListenOn, uint16 portNumber) {
m_listenSocket = CreateOverlappedSocket();

sockaddr_in serverAddress = { };
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = addressToListenOn;
serverAddress.sin_port = htons(portNumber);

auto result = bind(m_listenSocket, (sockaddr*)&serverAddress, sizeof(serverAddress));
if(result == -1) {
cout << "bind() => " << WSAGetLastError() << endl;
return;
}

result = listen(m_listenSocket, SOMAXCONN);
if(result == SOCKET_ERROR) {
cout << "listen() => " << WSAGetLastError() << endl;
return;
}

m_acceptExFn = LoadAcceptEx(m_listenSocket);
if(m_acceptExFn == FALSE) {
cout << "LoadAcceptEx() => " << WSAGetLastError() << endl;
return;
}

AssociateDevice((HANDLE)m_listenSocket);
}

void PostAccept() {
DWORD bytesReceived_ = 0;
DWORD addressSize = sizeof(sockaddr_in) + 16;
auto result = m_acceptExFn(m_listenSocket, m_socket, m_data, 0, addressSize, addressSize, &bytesReceived_, 0/*&m_acceptContext*/);
if(result == 0) {
if(WSAGetLastError() != WSA_IO_PENDING)
cout << "m_acceptExFn() => " << WSAGetLastError() << endl;
return;
}

result = PostQueuedCompletionStatus(m_ioCompletionPort, 0, 0, 0/*&m_acceptContext*/);
if(result == 0) {
cout << "PostQueuedCompletionStatus() => " << WSAGetLastError() << endl;
return;
}
}
[/CODE]

Share this post


Link to post
Share on other sites
AcceptEx() requires that you specify an LPOVERLAPPED for the final parameter. The [url="http://msdn.microsoft.com/en-us/library/windows/desktop/ms737524(v=vs.85).aspx"]documentation[/url] explicitly states that it cannot be NULL.

Share this post


Link to post
Share on other sites
If you want to get up to speed on IOCP in general you might find my free IOCP client/server code of some use, it's pretty old now but it works well and the articles that I wrote for CodeProject explain what's going on.

You can download the code from [url="http://www.serverframework.com/products---the-free-framework.html"]here[/url] and there are links to the articles that explain it.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this