All pastes #593461 Raw Edit

Untitled

public text v1 · immutable
#593461 ·published 2007-06-28 10:27 UTC
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;
}