1 Pluspunkt 0 Minuspunkte

Ich habe einen Server in C der Verbindungen in einem eigenen Thread abwickelt.

#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <windows.h>

DWORD WINAPI client_handler(LPVOID lpParam) {

    SOCKET clientSocket = (SOCKET)lpParam;

    send(clientSocket, "Hello from server!", sizeof("Hello from server!"), 0);
    
    closesocket(clientSocket);
    
    return NULL;
    
}

int main() {

    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(12345);
    serverAddr.sin_addr.s_addr = INADDR_ANY;

    bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));

    listen(serverSocket, 5);

    while (1) {
    
        SOCKET clientSocket;
        struct sockaddr_in clientAddr;
        int clientAddrLen = sizeof(clientAddr);

        clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen);

        DWORD threadId;
        HANDLE threadHandle = CreateThread(NULL, 0, client_handler, (LPVOID)clientSocket, 0, &threadId);

        if (threadHandle == NULL) {
            perror("CreateThread");
            return 1; // Fehler beim Erstellen des Threads
        }

        CloseHandle(threadHandle);
    }

    closesocket(serverSocket);

    WSACleanup();

    return 0;

}

Es kann vorkommen das ein Thread manchmal etwas länger dauert und ich möchte nach einer bestimmten Zeit kontrollieren ob der Socket noch aktiv ist und brauche dazu eine Art Userliste in der alle verbundenen Clients mit ihrem Socket gespeichert sind um Nachrichten an den Socket eines bestimmten User senden zu können.

von  

1 Antwort

0 Pluspunkte 0 Minuspunkte

Zuerst erstelle eine Struktur "ClientInfo" die einen Eintrag in der Userliste repräsentiert. Dann erstelle ein Array "clients" in dem du die "ClientInfo" Objekte speichern kannst und eine Variable "numClients" für die Anzahl an verbundenen Usern.

typedef struct {
    SOCKET socket;
    char username[20];
} ClientInfo;

ClientInfo clients[10];
int numClients = 0;

Nachdem der neue Client akzeptiert wurde erstellst du eine Instanz der Struktur "ClientInfo" und speicherst den Socket und den Usernamen darin. Das Objekt speicherst du im Array "clients" und erhöhst die Anzahl an Verbindungen "numClients".

ClientInfo clientInfo; // Neues clientInfo Objekt erzeugen
clientInfo.socket = clientSocket; // Socket speichern
strcpy(clientInfo.username, "anonymous"); // Username setzen

clients[numClients++] = clientInfo; // in die Userliste einfügen

Anstatt den clientSocket direkt an den Thread zu übergeben übergibst du einen Pointer auf das gespeicherte "ClientInfo" Objekt in der Userliste "clients".

HANDLE threadHandle = CreateThread(NULL, 0, client_handler, (LPVOID)&clients[numClients - 1], 0, &threadId);

Noch einmal alles zusammen.

#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <windows.h>

typedef struct {
    SOCKET socket;
    char username[20];
} ClientInfo;

ClientInfo clients[10];
int numClients = 0;

DWORD WINAPI client_handler(LPVOID lpParam) {

    ClientInfo* clientInfo = (ClientInfo*)lpParam;    
    SOCKET clientSocket = clientInfo->socket;
    
    char *data;
    sprintf(data, "Hello from %s", clientInfo->username);
    
    send(clientSocket, data, sizeof(data), 0);
    
    closesocket(clientSocket);
    
    return NULL;
    
}

int main() {

    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(12345);
    serverAddr.sin_addr.s_addr = INADDR_ANY;

    bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));

    listen(serverSocket, 5);

    while (1) {
    
        SOCKET clientSocket;
        struct sockaddr_in clientAddr;
        int clientAddrLen = sizeof(clientAddr);

        clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen);
        
        ClientInfo clientInfo;
        clientInfo.socket = clientSocket;
        strcpy(clientInfo.username, "anonymous");
        clients[numClients++] = clientInfo;

        DWORD threadId;
        HANDLE threadHandle = CreateThread(NULL, 0, client_handler, (LPVOID)&clients[numClients - 1], 0, &threadId);
        
        if (threadHandle == NULL) {
            perror("CreateThread");
            return 1; // Fehler beim Erstellen des Threads
        }

        CloseHandle(threadHandle);
    }

    closesocket(serverSocket);

    WSACleanup();

    return 0;

}
von (716 Punkte)