Idea jest taka - mamy serwerek na socketach, obsługujący klientów łączących się telnetem. Łączy się nowy klient - tworzony jest nowy wątek i tam odbywa się komunikacja z owym klientem, niezależnie od reszty. Max dopuszczalna liczba klientów jest stała. Poza tym, każdy z nich, "dostaje" jeden wątek i dostęp do jednego elementu z tablicy obiektów.
Problem pojawia się, gdy łączy się nowy klient, a limit jest już wykorzystany. Na razie rozwiązanie wygląda mniej więcej tak:
listenSck = socket ...;
while(1)
{
if(0 != dostKl())//jeśli nie przekroczono limitu
{
int pierwszeWolnemiejsce = znajdz();//mamy indeks do obiektu nieużywanego przez klienta
obiekty[pierwszeWolnemiejsce].ustawZajety();//rezerwujemy
obiekty[pierwszeWolnemiejsce].ustaw(accept(listenSck,NULL,NULL));//socket dla wolnego
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)obiekty[pierwszeWolnemiejsce].funkcja, &obiekty[pierwszeWolnemiejsce], 00,0);//nowy wątek
}
}
W przydzielonej funkcji, po zakończeniu zabawy z klientem, zmieniany jest warunek dostępności i obiekt można przydzielic nowemu klientowi.
Jeśli chodzi o działanie - jest ok, jak jest za dużo klientów, ci powyżej limitu wiszą sobie na sockecie (w konsoli nie ma żadnej wiadomości). Jak ktoś się rozłączy - w jego miejsce wskakuje pierwszy z kolejki (zakładam, że socket sobie kolejkuje nowych klientów) i wszystko jest jak trzeba.
Niestety nie do końca jest tak różowo. Po pierwsze - jeśli na takim "wiszącym" kliencie sobie coś wpiszemy, jest to w jakiś sposób przechowywane przez socket. Czyli - jeśli w wątku przesyłam napis do klienta, czekam na dowolny klawisz i go rozłączam, kiedy zwolni się miejsce, to, co wcześniej napisał klient, zostanie mi wrzucone na recv, mimo, że to, co klient wysłał wcześniej, nie jest mi potrzebne.
Po drugie - chciałbym pozbyć się wiszących klientów - jak nie ma miejsc - send(papa) i disconnect. Niby wydaje się to proste:
listenSck = socket ...;
while(1)
{
if(0 != dostKl())//jeśli nie przekroczono limitu
{
int pierwszeWolnemiejsce = znajdz();//mamy indeks do obiektu nieużywanego przez klienta
obiekty[pierwszeWolnemiejsce].ustawZajety();//rezerwujemy
obiekty[pierwszeWolnemiejsce].ustaw(accept(listenSck,NULL,NULL));//socket dla wolnego
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)obiekty[pierwszeWolnemiejsce].funkcja, &obiekty[pierwszeWolnemiejsce], 00,0);//nowy wątek
}
else
{
SOCKET sckTempSocket = accept(listenSck, NULL, NULL);//akceptujemy
send(sckTempSocket, "bye!",strlen("bye!"), 0 );//żegnamy
closesocket(sckTempSocket);//rozłączamy
}
}
ale jednak nie działa to tak, jak tego oczekuję - mam np. limit 10 klientów, połączy się 10 - jest ok, połączy się 11 - wywali. Z 10 połączonych odejdzie 1 - niby powinna być już możliwość połączenia, ale w praktyce okazuje się, że klient zostaje wywalony - muszę połączyć się jeszcze raz i dopiero wtedy jest ok.
Zakładam, że jak mam 10 klientów, program wskakuje w elsa i czeka na accepcie. Mimo, że ktoś się rozłączył, program nie sprawdza, czy jest wolne miejsce.
Ma ktoś jakiś pomysł?