Multi-threaded TCP server

 multi-threaded TCP server

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <direct.h>  // For _mkdir

#define SERVERPORT 9000
#define BUFSIZE 512

void err_quit(const char *msg) {
    fprintf(stderr, "%s\n", msg);
    exit(1);
}

void err_display(const char *msg) {
    fprintf(stderr, "%s\n", msg);
}

DWORD WINAPI client_handler(LPVOID lpParam) {
    SOCKET client_sock = (SOCKET)lpParam;
    char client_name[50] = {0};
    int retval;

    // Receive client name
    retval = recv(client_sock, client_name, sizeof(client_name) - 1, 0);
    if (retval <= 0) {
        closesocket(client_sock);
        return 0;
    }
    client_name[retval] = '\0';

    printf(">>> Client connected, Client name: %s <<<\n", client_name);

    // Handle communication
    char buf[BUFSIZE + 1];
    while (1) {
        retval = recv(client_sock, buf, BUFSIZE, 0);
        if (retval <= 0) break;

        buf[retval] = '\0';
        printf("[%s]: %s\n", client_name, buf);

        if (strncmp(buf, "sendfile", 8) == 0) {
            // Receive filename
            char filename[256] = {0};
            int index = 0;
            while (1) {
                int r = recv(client_sock, &filename[index], 1, 0);
                if (r <= 0 || index >= 255) break;
                if (filename[index] == '\0') break;
                index++;
            }

            // Receive file size
            long filesize;
            int r = recv(client_sock, (char*)&filesize, sizeof(filesize), 0);
            if (r <= 0) {
                printf("Error receiving file size.\n");
                closesocket(client_sock);
                return 0;
            }

            // Ensure received directory exists
            _mkdir("received");

            // Create path for saving
            char filepath[300];
            sprintf(filepath, "received/%s", filename);

            printf("Receiving file: %s (%ld bytes)\n", filepath, filesize);

            FILE *file = fopen(filepath, "wb");
            if (!file) {
                printf("Error: Cannot create file %s\n", filepath);
                break;
            }

            long received = 0;
            while (received < filesize) {
                int bytes = recv(client_sock, buf, BUFSIZE, 0);
                if (bytes <= 0) break;
                fwrite(buf, 1, bytes, file);
                received += bytes;
            }

            fclose(file);
            printf("File received and saved to: %s\n", filepath);
        } else {
            send(client_sock, buf, retval, 0); // Echo message
        }
    }

    printf("Client %s disconnected.\n", client_name);
    closesocket(client_sock);
    return 0;
}

int main() {
    int retval;
    WSADATA wsa;

    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
        return 1;

    SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sock == INVALID_SOCKET) err_quit("socket()");

    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(SERVERPORT);
    retval = bind(listen_sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
    if (retval == SOCKET_ERROR) err_quit("bind()");

    retval = listen(listen_sock, SOMAXCONN);
    if (retval == SOCKET_ERROR) err_quit("listen()");

    printf(">>> Welcome to Kompong Thom Server Boy Smos SOTHEA <3 <<<\n");
    printf("--> I'm Waiting Clients to Connect me -.- <--\n");

    while (1) {
        struct sockaddr_in clientaddr;
        int addrlen = sizeof(clientaddr);
        SOCKET client_sock = accept(listen_sock, (struct sockaddr *)&clientaddr, &addrlen);
        if (client_sock == INVALID_SOCKET) {
            err_display("accept()");
            continue;
        }

        CreateThread(NULL, 0, client_handler, (LPVOID)client_sock, 0, NULL);
    }

    closesocket(listen_sock);
    WSACleanup();
    return 0;
}

Post a Comment

0 Comments