Witam,
Chciałbym Was prosić abyście ocenlili poprawność tego pomysłu i odpowiedzieli na kilka pytań . Dlaczego piszę tu a nie próbuję tego napisać w kodzie ?. Ponieważ już próbowałem i jest tutaj jakiś większy błąd logiczny którego nie potrafię znaleźć.
Otóż, do napisania mam program który opiera się na zasadzie Klient-Server . Klientów może być dowolna ilość,mogą przychodzić oraz odchodzić w każdej chwili . Klient komunikuje się z serverem poprzez sockety ( konkretnie DataIn/OutputStream ),server z klientem tak samo.
Myślałem zatem że dobrym pomysłem będzie napisanie tego na 3 klasach ( Klient,Server,Watek_Servera).
W klasie Server oczekuję na połączenie,jeżeli ono nastąpi do dodaję wątek klienta do Mapy :
private static Map<String, Watek_Serveraa> mapa = Collections.synchronizedMap( new HashMap<String,Watek_Serveraa>() );
/**
*
*
*/
mapa.put(pseudonim_gracza,new Watek_Serveraa(klient,mapa,x,y) ) ;
Thread abc =mapa.get(pseudonim_gracza);
abc.start();
Mapę tę przekazuję do klasy Watek_Servera ponieważ tam muszę pracować z wszystkimi wątkami.
W klasie Watek_Servera chciałem napisać coś mniej więcej takiego.
(Jestem już w metodzie run() pętli while(true) klasy WS )Za pomocą iteratora wybieram pierwszy element z mapy i wpisuję sobie do String jego własny ID. Następnie w 2 pętli for za pomocą iteratora2 wysyłam do wszystkich klientów informacje czyj ruch jest teraz
Chciałem to zrobić mniej więcej tak :
synchronized(this) {
for( Map.Entry<String, Watek_Serveraa> iterator1 : mapa.entrySet() )
{
String kto_jedzie=iterator1.getKey();
System.out.println(kto_jedzie);
for( Map.Entry<String, Watek_Serveraa> iterator2 : mapa.entrySet() )
{
try
{
iterator2.getValue().dos.writeUTF(kto_jedzie);
}
catch(Exception ex) { System.out.println("Blad watek wysylanie do klientow kto jedzie "); }
}
String czynnosc = iterator1.getValue().wejscie.readUTF();
if( czynnosc.equals("Ruch") )
{
try
{
if( vektor_ruchow.size() > 0 )
{
iterator1.getValue().writeUF("Stare ruchy");
/** wysłanie obiektami poprzednich ruchów
}
else
{
wyjscie.writeUTF("Nowe ruchy");
//wyjscie.flush();
}
boolean ruch_wykonany = false ;
while( ruch_wykonany == false )
{
String ruch_klienta = iterator1.getValue().wejscie.readUTF();
System.out.println("Ruch klienta :"+ruch_klienta);
drukuj();
if( sprawdz(ruch_klienta)==true )
{
//System.out.println("Jestem tu !");
iterator1.getValue().wyjscie.writeUTF("Poprawny");
//wyjscie.flush();
//System.out.println("Jestem tu 2!");
String wiadomosc_lokalna = iterator1.getValue().wejscie.readUTF();
System.out.println("Wiad: "+wiadomosc_lokalna);
if( wiadomosc_lokalna.equals("Wykonany") )
{
//System.out.println("Jestem tu 3!");
ruch_wykonany = true;
ruch(ruch_klienta,kto_jedzie);
if( (koniec_gry(kto_jedzie,liczba_symboli)))
{
/**Zapis do pliku **/
}
}
else if( wiadomosc_lokalna.equals("Nie wykonany") )
{
//System.out.println("Jestem tu 4!");
}
}
else
{
//System.out.println("Jestem tu 5!");
iterator1.getValue().wyjscie.writeUTF("Nie poprawny");
}
}
}
catch(Exception ex) { System.out.println(" Blad watek wysylanie do klientow ruchu"); }
}
}
Klient z kolei rozpoznaje co Server mu napisał i w zależności od tego podejmuje konkretną akcje.
Wszystko psuję się w momencie nawiązania "dialogu" pomiędzy konkretnym klientem a serverem . Klient ma za zadanie powiedzieć serverowi co chce zrobić ( Ruszyć się,Wyjść .... ) Server dostaje komendę i w zależności od tego co to za komenda robi określone rzeczy,problem w tym że komunikacja pomiędzy Klientem a Serverm ( która opiera się na Stringach) zawodzi ponieważ drukując to co dostaje Klient okazuje się,że jest to nie ta komenda którą Klient miał otrzymać , staje w miejscu ...
Można by pomyśleć że wysyłam jakąś komendę i jej nie odbieram dlatego wszystko stoi . Jednak sprawdziłem 2 razy i każde wysłanie komendy przez Server/Klient ma przypisane odebranie jej przez stronę przeciwną . Podajrzewam że on jakoś gubi po drodze te komendy albo mu się klienci mylą .
Mam jeszcze takie pytania :
- Czy wyżej opisana komunikacja jest dobrym pomysłem ?.
- Czy chcąc wysłać komunikat do klienta którego wybieram w I pętli for używam : iterator1.getValue().dos.writeUTF(msg) czy też normalne dos.writeUTF();
- Komunikacja,w teorii,miała być zrobiona tak że nowy klient oczekuję aż stary się ruchy i dopiero wtedy jemu server wysyła info że może jechać(iterator zmieni obiekt). Jak to się dzieje że dla ID klienta( 1 : "A" 2 : "B") zachodzi oczekiwanie na ruch poprzedniego klienta a dla ID ( 1 : "A" 2 : "X") nagle obaj naraz chcą jechać ?. Dodawanie klientów mam zrobione tak :
boolean pseudonim = false ;
while( pseudonim == false )
{
pseudonim = pseudonim_funkcja();
}
public static boolean pseudonim_funkcja()
{
boolean pseudonim = false;
try
{
wyjscie.writeUTF("Pseudonim ?");
pseudonim_gracza = wejscie.readUTF();
System.out.println("psuedo "+pseudonim_gracza);
// Vector<String> vektor_nickow = new Vector <String> ();
if( vektor_nickow.contains(pseudonim_gracza) )
{
wyjscie.writeUTF("Nick zajety.Wybierz inny ");
pseudonim = false ;
}
else
{
wyjscie.writeUTF("Gracz poprawnie zarejestrowany na serverze");
vektor_nickow.add(pseudonim_gracza);
pseudonim = true;
}
}
catch(Exception ex){ System.out.println(" Server blad pseudonim");}
return pseudonim;
}
- Jak to się dzieje że "gdy nagle obaj chcą jechać" to Server nie zgubi komunikatu i będą mogli jechać ( nastąpi po stronie klienta odpowiednia reakcja na komunikat servera "Poprawny" . Natomiast gdy jeden oczekuję na ruch drugiego,to ten drugi klient NIGDY nie otrzyma komunikatu "Poprawny" , zamiast tego w to miejsce otrzymuję komunikat "Nowe ruchy" przez co nie może ruszyć się dalej.
Z góry bardzo bardzo dziękuję za przeczytanie moich wypocin .
Pozdrawiam