Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <WinBase.h>
- #include <errhandlingapi.h>
- #include <handleapi.h>
- #include <inttypes.h>
- #include <minwindef.h>
- #include <process.h>
- #include <stdbool.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <synchapi.h>
- #include <vcruntime.h>
- #include <winnt.h>
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #pragma comment(lib, "Ws2_32.lib")
- #define lengthof(x) (sizeof(x) / sizeof((x)[0]))
- #define PORT "27015"
- enum CONSTANT { MAX_THREAD_NUMBER = 5 };
- char *input(uint16_t maxLength) {
- if (!maxLength) {
- return NULL;
- }
- int32_t inputStringSize = maxLength + 2;
- char *inputString = malloc(inputStringSize);
- if (!inputString) {
- return NULL;
- }
- if (!fgets(inputString, inputStringSize, stdin)) {
- free(inputString);
- while (getchar() != '\n') {
- }
- return NULL;
- }
- if (inputString[0] == '\n') {
- free(inputString);
- return NULL;
- }
- size_t inputStringLength = strlen(inputString);
- char *lastStringCharacterPtr = &(inputString[inputStringLength - 1]);
- if (*lastStringCharacterPtr != '\n') {
- free(inputString);
- while (getchar() != '\n') {
- }
- return NULL;
- }
- *lastStringCharacterPtr = '\0';
- char *string = realloc(inputString, inputStringLength);
- if (!string) {
- free(inputString);
- return NULL;
- }
- return string;
- }
- struct addrinfo *setupServer() {
- WSADATA wsaData = {0};
- int error = WSAStartup(MAKEWORD(2, 2), &wsaData);
- if (error != 0) {
- printf("WSAStartup() failed with error: %d\n", error);
- return NULL;
- }
- struct addrinfo *host = NULL;
- error = getaddrinfo(
- NULL, PORT,
- &((struct addrinfo){
- .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP, .ai_flags = AI_PASSIVE}),
- &host);
- if (error != 0) {
- printf("getaddrinfo() failed with error: %d\n", error);
- WSACleanup();
- return NULL;
- }
- return host;
- }
- SOCKET getListeningSocket(int aiFamily, int type, int protocol, const struct sockaddr *name, int namelen) {
- SOCKET listeningSocket = socket(aiFamily, type, protocol);
- if (listeningSocket == INVALID_SOCKET) {
- printf("socket() failed with error: %d\n", WSAGetLastError());
- return INVALID_SOCKET;
- }
- if (bind(listeningSocket, name, namelen) == SOCKET_ERROR) {
- printf("bind() failed with error: %d\n", WSAGetLastError());
- closesocket(listeningSocket);
- return INVALID_SOCKET;
- }
- if (listen(listeningSocket, SOMAXCONN) == SOCKET_ERROR) {
- printf("listen() failed with error: %d\n", WSAGetLastError());
- closesocket(listeningSocket);
- return INVALID_SOCKET;
- }
- return listeningSocket;
- }
- void inputThread(void *arguments) {
- (void)arguments;
- while (true) {
- char *string = input(4);
- if (!string) {
- puts("Invalid input");
- continue;
- }
- if (strcmp("exit", string) != 0) {
- free(string);
- continue;
- }
- free(string);
- abort();
- return;
- }
- }
- typedef struct {
- SOCKET socket;
- HANDLE semaphore;
- uint64_t connectionNumber;
- } ArgumentStore;
- void clientConnectionThread(void *arguments) {
- ArgumentStore *argumentStorePtr = (ArgumentStore *)arguments;
- printf("Connected: %" PRIu64 "\n", argumentStorePtr->connectionNumber);
- int receivedByteNumber = 0;
- char buffer[512] = {0};
- do {
- receivedByteNumber = recv(argumentStorePtr->socket, buffer, lengthof(buffer), 0);
- } while (receivedByteNumber > 0);
- if (!receivedByteNumber) {
- printf("Connection closing...\n");
- if (shutdown(argumentStorePtr->socket, SD_SEND) == SOCKET_ERROR) {
- printf("shutdown() failed with error: %d\n", WSAGetLastError());
- }
- } else {
- printf("recv() failed with error: %d\n", WSAGetLastError());
- }
- closesocket(argumentStorePtr->socket);
- printf("Disconnected: %" PRIu64 "\n", argumentStorePtr->connectionNumber);
- if (!ReleaseSemaphore(argumentStorePtr->semaphore, 1, NULL)) {
- printf("ReleaseSemaphore() failed with error: %lu\n", GetLastError());
- }
- free(argumentStorePtr);
- }
- int main() {
- _beginthread(inputThread, 0, NULL);
- struct addrinfo *host = setupServer();
- if (host == NULL) {
- return 1;
- }
- HANDLE semaphore = CreateSemaphore(NULL, MAX_THREAD_NUMBER, MAX_THREAD_NUMBER, NULL);
- SOCKET listeningSocket = INVALID_SOCKET;
- uint64_t connectionNumber = 0;
- while (true) {
- if (WaitForSingleObject(semaphore, 0) != WAIT_OBJECT_0) {
- if (listeningSocket != INVALID_SOCKET) {
- closesocket(listeningSocket);
- listeningSocket = INVALID_SOCKET;
- }
- continue;
- }
- if (listeningSocket == INVALID_SOCKET) {
- listeningSocket = getListeningSocket(host->ai_family, host->ai_socktype, host->ai_protocol, host->ai_addr,
- (int)(host->ai_addrlen));
- }
- if (listeningSocket == INVALID_SOCKET) {
- break;
- }
- SOCKET clientSocket = accept(listeningSocket, NULL, NULL);
- if (clientSocket == INVALID_SOCKET) {
- printf("accept() failed with error: %d\n", WSAGetLastError());
- break;
- }
- ArgumentStore *argumentStorePtr = malloc(sizeof(*argumentStorePtr));
- if (!argumentStorePtr) {
- puts("malloc() failed");
- break;
- }
- *argumentStorePtr = (ArgumentStore){clientSocket, semaphore, connectionNumber};
- _beginthread(clientConnectionThread, 0, argumentStorePtr);
- ++connectionNumber;
- }
- freeaddrinfo(host);
- if (listeningSocket != INVALID_SOCKET) {
- closesocket(listeningSocket);
- }
- WSACleanup();
- CloseHandle(semaphore);
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement