#include <winsock2.h>
#include <mswsock.h>
#include <iostream.h>
#include <conio.h>
#pragma comment(lib, "ws2_32.lib")
#define BUFFER_SIZE 4096
SOCKET Sockets[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT Events[WSA_MAXIMUM_WAIT_EVENTS];
WSAOVERLAPPED Overlappeds[WSA_MAXIMUM_WAIT_EVENTS];
char sBuffer[WSA_MAXIMUM_WAIT_EVENTS][BUFFER_SIZE];
SOCKET Listen;
DWORD dwTotal = 0;
volatile long dwClients = 0;
HANDLE hThread;
DWORD GetInvalidIndex();
DWORD WINAPI ThreadAccept(LPVOID lpParam);
DWORD WINAPI WorkerThread(LPVOID lpParam);
char sendBuffer[] = "/t Welcome to Overlapped IO Module server/r/n";
void main()
{
WSADATA wsaData;
int nRet;
nRet = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(nRet != 0)
{
cout <<"WSAStartup Failed: " <<WSAGetLastError() <<endl;
return;
}
Listen = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == Listen)
{
cout <<"WSASocket Failed: " <<WSAGetLastError() <<endl;
WSACleanup();
return;
}
SOCKADDR_IN inAddr;
inAddr.sin_family = AF_INET;
inAddr.sin_addr.s_addr = htonl(INADDR_ANY);
inAddr.sin_port = htons(5150);
nRet = bind(Listen, (PSOCKADDR)&inAddr, sizeof(inAddr));
if (SOCKET_ERROR == nRet)
{
closesocket(Listen);
cout <<"bind Failed: " <<WSAGetLastError() <<endl;
WSACleanup();
return;
}
nRet = listen(Listen, 20);
if (SOCKET_ERROR == nRet)
{
closesocket(Listen);
cout <<"listen Failed: " <<WSAGetLastError() <<endl;
WSACleanup();
return;
}
for(int i=0; i<WSA_MAXIMUM_WAIT_EVENTS; i++)
{
Sockets[i] = INVALID_SOCKET;
Events[i] = WSA_INVALID_EVENT;
ZeroMemory(&(Overlappeds[i]), sizeof(WSAOVERLAPPED));
ZeroMemory(&sBuffer[i], BUFFER_SIZE);
}
hThread = CreateThread(NULL, 0, ThreadAccept, NULL, 0, NULL);
if(NULL == hThread)
{
closesocket(Listen);
cout <<"CreateThread Failed: " <<GetLastError() <<endl;
WSACleanup();
return;
}
CloseHandle(hThread);
hThread = CreateThread(NULL, 0, WorkerThread, NULL, CREATE_SUSPENDED, NULL);
if(NULL == hThread)
{
closesocket(Listen);
cout <<"CreateThread Failed: " <<GetLastError() <<endl;
WSACleanup();
return;
}
cout <<"Enter 'q' to exit: " <<endl;
while(getch() != 'q');
closesocket(Listen);
WSACleanup();
CloseHandle(hThread);
cout <<"Main thread will exit " <<endl;
getch();
}
DWORD GetInvalidIndex()
{
for(int i=0; i<WSA_MAXIMUM_WAIT_EVENTS; i++)
{
if(Sockets[i] == INVALID_SOCKET)
return i;
}
return -1;
}
DWORD WINAPI ThreadAccept(LPVOID lpParam)
{
SOCKET client;
int nRet;
WSAEVENT hEvent, Temp;
WSABUF wsaBuf;
DWORD dwRecv;
DWORD dwSend;
DWORD dwFlag;
DWORD dwIndex = -1;
while(true)
{
client = WSAAccept(Listen, NULL, NULL, NULL, 0);
if(client == INVALID_SOCKET)
{
cout <<"WSAAccept Failed: " <<WSAGetLastError() <<endl;
cout <<"ThreadAccept thread exit " <<endl;
return 0;
}
if(dwTotal >= WSA_MAXIMUM_WAIT_EVENTS)
{
dwIndex = GetInvalidIndex();
if(-1 == dwIndex)
{
cout <<"Too many connections " <<endl;
closesocket(client);
continue;
}
}
else
{
dwIndex = dwTotal;
}
hEvent = WSACreateEvent();
if(WSA_INVALID_EVENT == hEvent)
{
cout <<"WSACreateEvent Failed: " <<WSAGetLastError() <<endl;
closesocket(client);
return 0;
}
Sockets[dwIndex] = client;
Temp = Events[dwIndex];
Events[dwIndex] = hEvent;
if(WSA_INVALID_EVENT != Temp)
{
WSACloseEvent(Temp);
}
ZeroMemory(&(Overlappeds[dwIndex]), sizeof(WSAOVERLAPPED));
ZeroMemory(&sBuffer[dwIndex], BUFFER_SIZE);
Overlappeds[dwIndex].hEvent = hEvent;
wsaBuf.buf = sBuffer[dwIndex];
wsaBuf.len = BUFFER_SIZE;
dwRecv = 0;
dwFlag = 0;
nRet = WSARecv(client, &wsaBuf, 1, &dwRecv, &dwFlag, &(Overlappeds[dwIndex]), NULL);
if(SOCKET_ERROR == nRet)
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
cout <<"WSARecv Failed: " <<WSAGetLastError() <<endl;
closesocket(client);
Sockets[dwIndex] = INVALID_SOCKET;
ZeroMemory(&(Overlappeds[dwIndex]), sizeof(WSAOVERLAPPED));
ZeroMemory(&(sBuffer[dwIndex]), BUFFER_SIZE);
continue;
}
}
ZeroMemory(&(Overlappeds[dwIndex]), sizeof(WSAOVERLAPPED));
wsaBuf.buf = sendBuffer;
wsaBuf.len = strlen(sendBuffer);
dwSend = 0;
dwFlag = 0;
nRet = WSASend(client, &wsaBuf, 1, &dwSend, dwFlag, &(Overlappeds[dwIndex]), NULL);
if(SOCKET_ERROR == nRet)
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
cout <<"WSASend Failed: " <<WSAGetLastError() <<endl;
closesocket(client);
Sockets[dwIndex] = INVALID_SOCKET;
ZeroMemory(&(Overlappeds[dwIndex]), sizeof(WSAOVERLAPPED));
ZeroMemory(&(sBuffer[dwIndex]), BUFFER_SIZE);
continue;
}
}
if(dwTotal < WSA_MAXIMUM_WAIT_EVENTS) dwTotal++;
InterlockedIncrement(&dwClients);
if(dwClients == 1) ResumeThread(hThread);
cout <<"Client connected with socket: " <<client <<" Total = " <<dwClients <<endl;
cout <<"Send: " <<wsaBuf.buf <<endl;
}
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
DWORD dwEvent;
DWORD Index;
WSABUF wsaBuf;
DWORD dwRecv;
DWORD dwSend;
DWORD dwFlag;
int nRet;
//WSAOVERLAPPED ol;
while(TRUE)
{
dwEvent = WSAWaitForMultipleEvents(dwTotal, Events, FALSE, 10/*WSA_INFINITE*/, FALSE);
if(WSA_WAIT_TIMEOUT == dwEvent)
{
continue;
}
if(WSA_WAIT_FAILED == dwEvent)
{
cout <<"WSAWaitForMultipleEvents Failed: " <<WSAGetLastError() <<endl;
return 0;
}
Index = dwEvent - WSA_WAIT_EVENT_0;
WSAResetEvent(Events[Index]);
DWORD dwBytes = 0;
DWORD dwFlags = 0;
WSAGetOverlappedResult(Sockets[Index], &(Overlappeds[Index]), &dwBytes, FALSE, &dwFlags);
if(dwBytes == 0)
{
cout <<"Client disconnected: " <<Sockets[Index] <<endl;
ZeroMemory(&(Overlappeds[Index]), sizeof(WSAOVERLAPPED));
ZeroMemory(&(sBuffer[Index]), BUFFER_SIZE);
closesocket(Sockets[Index]);
Sockets[Index] = INVALID_SOCKET;
InterlockedDecrement(&dwClients);
if(dwClients == 0) SuspendThread(hThread);
continue;
}
cout<<"Recv: " <<sBuffer[Index] <<endl;
/*
ZeroMemory(&ol, sizeof(WSAOVERLAPPED));
wsaBuf.buf = sBuffer[Index];
wsaBuf.len = BUFFER_SIZE;
dwRecv = 0;
dwSend = 0;
dwFlag = 0;
nRet = WSASend(Sockets[Index], &wsaBuf, 1, &dwSend, dwFlag, &ol, NULL);
if(SOCKET_ERROR == nRet)
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
cout <<"WSARecv Failed: " <<WSAGetLastError() <<endl;
closesocket(Sockets[Index]);
Sockets[Index] = INVALID_SOCKET;
continue;
}
}
*/
ZeroMemory(&(Overlappeds[Index]), sizeof(WSAOVERLAPPED));
ZeroMemory(&sBuffer[Index], BUFFER_SIZE);
Overlappeds[Index].hEvent = Events[Index];
wsaBuf.buf = sBuffer[Index];
wsaBuf.len = BUFFER_SIZE;
dwRecv = 0;
dwSend = 0;
dwFlag = 0;
nRet = WSARecv(Sockets[Index], &wsaBuf, 1, &dwRecv, &dwFlag, &(Overlappeds[Index]), NULL);
if(SOCKET_ERROR == nRet)
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
cout <<"WSARecv Failed: " <<WSAGetLastError() <<endl;
ZeroMemory(&(Overlappeds[Index]), sizeof(WSAOVERLAPPED));
ZeroMemory(&(sBuffer[Index]), BUFFER_SIZE);
closesocket(Sockets[Index]);
Sockets[Index] = INVALID_SOCKET;
InterlockedDecrement(&dwClients);
if(dwClients == 0) SuspendThread(hThread);
continue;
}
}
}
}