rendered paste body#include <WinSock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#define DEFAULT_PORT "33123"
#define MAX_THREADS 16
#define WINSOCK_INIT_ERROR 1
#define GETADDRINFO_ERROR 2
#define SOCKET_CREATE_ERROR 4
#define BIND_SOCKET_ERROR 8
#define LISTEN_SOCKET_ERROR 16
#define CLIENT_CONNECT_ERROR 32
int sockInit(void);
int sockListen(void);
int mainLoop(void);
DWORD WINAPI clientWork(LPVOID);
CRITICAL_SECTION CriticalSection;
int numClients = 0;
SOCKET ListenSocket = INVALID_SOCKET;
int
main(int argc, char *argv[])
{
int returnValue = 0;
returnValue += sockInit();
returnValue += sockListen();
if (returnValue) {
return returnValue;
}
InitializeCriticalSection(&CriticalSection);
// never returns
returnValue += mainLoop();
DeleteCriticalSection(&CriticalSection);
return returnValue;
}
int
sockInit(void)
{
int returnValue = 0;
int iResult;
WSADATA wsaData;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
returnValue += WINSOCK_INIT_ERROR;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
returnValue += GETADDRINFO_ERROR;
}
// Create a SOCKET for the server to listen for client connections
ListenSocket = socket(result->ai_family, result->ai_socktype, \
result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
returnValue += SOCKET_CREATE_ERROR;
}
// Setup the TCP listening socket
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
returnValue += BIND_SOCKET_ERROR;
}
return returnValue;
}
int
sockListen(void)
{
if (listen(ListenSocket, SOMAXCONN ) == SOCKET_ERROR) {
printf("Error at bind(): %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return LISTEN_SOCKET_ERROR;
}
return 0;
}
int
mainLoop(void)
{
int returnValue = 0;
SOCKET ClientSocket = INVALID_SOCKET;
DWORD dwThreadId[MAX_THREADS];
HANDLE hThread[MAX_THREADS];
while(true) {
if (numClients >= MAX_THREADS)
continue;
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
returnValue += CLIENT_CONNECT_ERROR;
break;
}
EnterCriticalSection(&CriticalSection);
numClients++;
LeaveCriticalSection(&CriticalSection);
hThread[numClients] = CreateThread(
NULL,
0,
clientWork,
&ClientSocket,
0,
&dwThreadId[numClients]);
if (hThread[numClients] == NULL)
ExitProcess(numClients);
}
return returnValue;
}
DWORD WINAPI
clientWork(LPVOID lpParam)
{
SOCKET *lSock;
lSock = (SOCKET *) lpParam;
EnterCriticalSection(&CriticalSection);
numClients--;
LeaveCriticalSection(&CriticalSection);
return 0;
}