Ostatnio stworzyłem dość prosty komunikator działający na zasadzie dwóch aplikacji : klient i serwer.
Generalnie chyba wszystko działa jak należy, tylko natrafiłem na pewien problem.
Z chwilą gdy klient łączy się z serwerem, przesyła do serwera nick użytkownika, a serwer zapisuje sobie ten nick i dodaje go do listboxa.
Wszystko fajnie, tylko pomyślałem, żeby zrobić to w odwrotną stronę : chciałem, żeby lista dostępnych użytkowników była widoczna na każdym kliencie.
Do rozsyłania wszelkich komunikatów itp z serwera do wszystkich klientów zrobiłem prostą funkcję.
KOD cpp: UKRYJ
void TForm17::Rozeslij(AnsiString wiadomosc){
for(int x = 0; x < ServerSocket1->Socket->ActiveConnections; x++){
ServerSocket1->Socket->Connections[x]->SendText(wiadomosc);
Sleep(1);
}
for(int x = 0; x < ServerSocket1->Socket->ActiveConnections; x++){
ServerSocket1->Socket->Connections[x]->SendText(wiadomosc);
Sleep(1);
}
Teraz oczywiście każdy pomyśli : WTF? Po co ci ten Sleep?
Bez tego Sleepa mój klient zostanie zalany pakietami i nie będzie wiedział o co chodzi, ale to wytłumaczę za chwilę.
Do synchronizacji listy aktualnie zalogowanych użytkowników zrobiłem kolejną prostą funkcję, która korzysta z funkcji podanej powyżej.
KOD cpp: UKRYJ
void TForm17::Synchronizuj(){
Sleep(5);
Rozeslij("synch");
Sleep(5);
for(int x = 0; x < ListBox1->Items->Count; x++){
Rozeslij(ListBox1->Items->Strings[x]);
Sleep(1);
}
Sleep(5);
Rozeslij("koniec");
Sleep(5);
}
Sleep(5);
Rozeslij("synch");
Sleep(5);
for(int x = 0; x < ListBox1->Items->Count; x++){
Rozeslij(ListBox1->Items->Strings[x]);
Sleep(1);
}
Sleep(5);
Rozeslij("koniec");
Sleep(5);
}
Zostawmy jeszcze na chwilę te Sleep'y. Jak już można się domyśleć, działanie tego wielce skomplikowanego procesu synchronizacji jest następujące:
1. Serwer wysyła do każdego klienta wiadomość "synch".
2. Klient w zdarzeniu OnRead sprawdza, czy przesłana do niego wiadomość to "synch". Jeśli tak, to ustawia odpowiednią zmienną na true i od tego momentu wszystkie wiadomości jakie dostanie, wpisuje do swojego ListBoxa. Oczywiście tymi wiadomościami są nazwy użytkowników.
3. Z chwilą gdy klient dostanie wiadomość "koniec", zmienna jest ustawiana na false i wszystkie komunikaty które od tej chwili dostaje, wpisuje normalnie do swojego Memo.
Jestem przekonany, że można zrobić to w jakiś cywilizowany sposób, a nie tak jak ja. Teraz co do tych Sleepów. Głównym problemem jest to, że muszę dać czas klientowi na odebranie tego komunikatu, przejście przez wszystkie if'y itd. W przeciwnym wypadku po stronie klienta panuje totalna anarchia. Problem ten występuje tylko gdy chce przeprowadzić synchronizację zaraz po podłączeniu klienta do serwera. W przeciwnym wypadku, gdy np zrobie sobie buttona z funkcją Synchronizuj(), wszystko będzie ok (oczywiście dalej wszystko na Sleepach);
Teraz pytania:
1. Jak przeprowadzać cały proces synchronizacji? Czy przebudować go całkiem, czy lekko zmodyfikować?
2. Jak (nie używając Sleepa) poczekać, aż serwer wyśle wszystkie informacje do klienta, a ten je odbierze?
Z góry dzięki za pomoc