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 http://askldjd.wordp...r-1-2-released/ as some kind of reference and tried to initialize basic IOCP and get it it working, however I get WSA_INVALID_PARAMETER error in GetQueuedCompletionStatus inside worker thread when client attempts to connect.
Here's my 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;
}
}