klient-serwer problem przy dołączaniu klientów

0

Próbuję zrobić w C serwer podobny do tego
http://www.wemif.pwr.wroc.pl/paluszynski/netw/w32_tcp3.html

To co stworzyłem początkowo działa, jeśli któryś klient się odłączy to pozostali też mogą wysyłać komunikaty, ale gdy dołączę nowego klienta po odłączeniu jednego z klientów to wtedy nie chce to działać. Niby ten nowy klient zostaje podłączony ale wiadomości od niego nie odbiera. Nie wiem co robię nie tak. Mógłby ktoś przejrzeć mój kod i mi pomóc?

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <string.h>

WSADATA wsaData;
SOCKET ssock;
SOCKET sock[4];
SOCKADDR_IN addr[4];
SOCKADDR_IN saddr;
fd_set gniazda;
int sizeAddr[4];
int ssizeAddr;
int err = 0, lK = 0;
HANDLE hThread;

DWORD WINAPI watekGry(LPVOID lpParam)
{
    int i = 0, j = 0, ret = 0;
    byte bufor[1];

    while (1) {
        if (lK > 0) {
            FD_ZERO(&gniazda);
            for (i = 0; i < lK; i++) {
                FD_SET(sock[i], &gniazda);
            }
            select(0, &gniazda, NULL, NULL, (struct timeval *) 0);
            for (i = 0; i < lK; i++) {
                if (FD_ISSET(sock[i], &gniazda)) {
                    ret = recv(sock[i], bufor, sizeof(bufor), 0);
                    printf("%d\n", bufor[0]);
                    if ((ret == 0) || (ret == WSAECONNRESET)) {
                        printf("Rozlaczono klienta %d.\n", i);
                        for (j = i; j < lK ; j++) {
                            sock[j] = sock[j + 1];
                            addr[j] = addr[j + 1];
                        }
                        if (lK > 0) lK--;
                        break;
                    }
                } else if (ret == SOCKET_ERROR) {
                    printf("Blad odbioru komunikatu od klienta: %d.\n", i);
                }
            }
        }
        Sleep(100);
    }
    return 1;
}

void main()
{
    int ii = 0;

    srand(time(NULL));
    err = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (err != 0) {
        printf("Błąd funkcji WSAStartup().\n");
        system("PAUSE");
        WSACleanup();
        return 1;
    }
    ssock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if(ssock == SOCKET_ERROR) {
        printf("Błąd funkcji socket().\n");
        system("PAUSE");
        WSACleanup();
        return 1;
    }
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(1000);
    saddr.sin_addr.s_addr = (INADDR_ANY);
    if(bind(ssock, (struct sockaddr *) &saddr, sizeof(saddr)) == SOCKET_ERROR) {
        printf("Blad funkcji bind().\n");
        system("PAUSE");
        closesocket(ssock);
        WSACleanup();
        return 1;
    }
    ssizeAddr = sizeof(saddr);
    for (ii = 0; ii < 4; ii++) {
        sizeAddr[ii] = sizeof(addr[ii]);
    }
    ioctlsocket(ssock, FIONBIO, 1);
    if (listen(ssock, SOMAXCONN == SOCKET_ERROR)) {
        printf("Błąd funkcji listen().\n");
        system("PAUSE");
        closesocket(ssock);
        WSACleanup();
        return 1;
    }
    hThread = CreateThread (NULL, 0, watekGry, (LPVOID)sock[lK], 0, NULL);
    if (hThread == NULL) {
        printf("Blad funkcji CreateThread().\n");
        return 1;
    }
    while (1) {
        if (lK < 4) {
            sock[lK] = accept(ssock, &addr[lK], &sizeAddr[lK]);
            if (sock[lK] == INVALID_SOCKET) {
                printf("Blad przy laczeniu klienta: %d.\n", lK);
            } else {
                TerminateThread(hThread,0);
                printf("Polonczono z klientem %d.\n", lK);
                FD_SET(sock[lK], &gniazda);
                hThread = CreateThread (NULL, 0, watekGry, (LPVOID)sock[lK], 0, NULL);
                lK++;
            }
        }
        Sleep(100);
    }
    for (ii = 3; ii >= 0; ii--)
        closesocket(sock[ii]);
    closesocket(ssock);
    WSACleanup();
    return 0;
}
0
           {
                TerminateThread(hThread,0);
                printf("Polonczono z klientem %d.\n", lK);
                FD_SET(sock[lK], &gniazda);
                hThread = CreateThread (NULL, 0, watekGry, (LPVOID)sock[lK], 0, NULL);
                lK++;
            }

Wydaje mi się że tu trzeba będzie coś zmienić. Wygląda to tak jakby po dodaniu klienta wątkeGry go "nie wiedział".

0

Zmodyfikowałem trochę watekGry, zmieniony fragment wygląda tak

for (i = 0; i < lK; i++) {
                if (FD_ISSET(sock[i], &gniazda)) {
                    ret = recv(sock[i], bufor, sizeof(bufor), 0);
                    if ((ret == 0) || (ret == WSAECONNRESET)) {
                        printf("Rozlaczono klienta %d.\n", i);
                        for (j = i; j < lK ; j++) {
                            sock[j] = sock[j + 1];
                            addr[j] = addr[j + 1];
                            sizeAddr[j] = sizeAddr[j + 1];
                        }
                        if (lK > 0) lK--;
                        break;
                    }
                 else
                    if (ret == SOCKET_ERROR) {
                        printf("Blad odbioru komunikatu od klienta: %d.\n", i);
                    } else {
                        printf("komunikat od klienta %d: %d\n", i, bufor[0]);
                    }
                }
            }

Gdy podłączę np dwóch klientów do serwera to działa to dobrze. Gdy np pierwszy klient się odłączy wtedy drugi klient staje się pierwszym. Problem pojawia się gdy wtedy podłączę klienta (to znaczy po odłączeniu któregoś z wcześniej podłączonych). Klient jest niby łączony, a nie są odbierane komunikaty od niego. Natomiast gdy wyślę komunikat z tego pierwszego klienta to wtedy po właściwym komunikacie wyświetla też błąd odbioru komunikatu od klienta drugiego. Gdy odłączę drugiego klienta (tego później podłączonego) to w wątku odbioru nie wyświetla komunikatu o jego odłączeniu. Wygląda to tak jakby rzeczywiście watekGdy nie widział klienta dodanego po odłączeniu któregoś z wcześniej podłączonych.

1 użytkowników online, w tym zalogowanych: 0, gości: 1