Jak przeskoczyć do innego wątku

Jak przeskoczyć do innego wątku
MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

Dzień dobry!

Mam problem z wątkami w Javie, dokładniej to mam program Client-Server i potrzebuje zrobić coś w tym stylu:

Jeśli klient podłączony jako drugi (i = 2) wyśle wiadomość do serwera,
to serwer wysyła klientowi podłączonemu jako pierwszy (i = 1) jakąś wiadomość.

Wielka prośba aby ktoś mi pomógł i nakierował mnie na jakieś rozwiązanie.
Siedzę już nad tym sporo czasu i nie mogę wymyślić rozwiązania.

Kod programów:

Server:

Kopiuj
import java.io.*;
import java.net.*;
import java.util.*;

class WatekGracza extends Thread
{
    int numerGracza;
    Socket socket;

    WatekGracza(Socket socket, int nr)
    {
        this.socket = socket;
        numerGracza = nr;
    }

    public void run()
    {
        try {
            PrintWriter out = new PrintWriter(
                        new OutputStreamWriter(
                    socket.getOutputStream()),true);


            BufferedReader in = new BufferedReader(
                                new InputStreamReader(
                                    socket.getInputStream()));

            int liczbaKlienta;

            String komunikat, odpowiedz="";
            while(true)
            {
                komunikat = in.readLine();
                System.out.println("Klient strzelił w:" + komunikat);
                liczbaKlienta = Integer.parseInt(komunikat);
                if(Server.ktosZgadl != -1)
                {
                    odpowiedz = "Przegrales, szybszy byl gracz numer " + Server.ktosZgadl;
                }
                else if(Server.liczba > liczbaKlienta) odpowiedz = "Za mało";
                else if(Server.liczba < liczbaKlienta) odpowiedz = "Za dużo";
                else if(Server.liczba == liczbaKlienta)
                {
                    odpowiedz = "Zgadłeś";
                    Server.ktosZgadl = numerGracza;
                }
                out.println(odpowiedz);
            }//koniec pętli while(true)
        } catch(Exception e) { System.out.println(e);}
    }//koniec funkcji uruchom()
}


public class Server
{
    public static int ktosZgadl = -1;
    public static int liczba;
    public static final int serverPort = 2020;
    private int i;
    ServerSocket s;
    /* Konstruktor próbuje utworzyć gniazdo */
    Server()
    {
        try{
            s = new ServerSocket(serverPort);
            System.out.println("Serwer dziala");
        }catch(Exception e) {
            System.out.println("Nie można utworzyć gniazda");
            System.exit(1);
        }
    }
    
    void uruchom() throws Exception
    {
        Random los = new Random();
        liczba = los.nextInt(101);
        while(true)
        {
            Socket socket = s.accept();
            WatekGracza gracz = new WatekGracza(socket, ++i);
            gracz.start();
        }

    }//koniec funkcji uruchom()


    public static void main(String args[]) throws Exception
    {
        Server server = new Server();
        server.uruchom();
        server.s.close();
    }
}

Client:

Kopiuj

import java.io.*;
import java.net.*;
import java.util.*;

public class Client
{
    private Socket socket;

    /* Konstruktor próbuje połączyć się z serwerem */
    Client()
    {
        try {
            socket = new Socket("localhost", 2020);
            System.out.println("Klient dziala");
        }
        catch(IOException e) {
            System.out.println("Uruchom serwer");
            System.exit(1);
        }
     }

     void uruchom() throws Exception
     {
        PrintWriter out = new PrintWriter(
                            new OutputStreamWriter(
                                socket.getOutputStream()),true);
        
        BufferedReader in = new BufferedReader(
                            new InputStreamReader(
                                socket.getInputStream()));
        
        Scanner czytacz = new Scanner(System.in);

        /* 2. Działanie klienta */
        String liczba, odSerwera;
        while(true) {
            System.out.println("Podaj zgadywaną liczbę: ");
            liczba = czytacz.nextLine();
            out.println(liczba);
            
            odSerwera = in.readLine();
            System.out.println(odSerwera);
            if(odSerwera.equals("Zgadłeś") 
            || odSerwera.startsWith("Przegrales"))
                break;
        }
        /* 3. Czynności po zakończeniu współpracy z serwerem */
        socket.close();
     }//koniec funkcji uruchom()

     public static void main(String args[]) throws Exception
     {
        Client client = new Client();
        client.uruchom();
     }
}

Pozdrawiam!

Kandif
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 231
1

Robiłem coś podobnego i zrobiłem tak:

Podczas podłączenia przypisywałem klientowi id według kolejności (klient uzyskiwał tą informacje od razu po połączeniu) po czym każdy wysłany pakiet indeksował klient podczas wysyłania do serwera, serwer oddzielał indeks od pozostałej informacji, potem wysyłał do pozostałych klientów (oprócz do tego który nadał tą wiadomość).

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

Jak wyżej, musisz na serwerze zwyczajnie pamiętać który wątek/który socket służy do komunikacji z danym klientem.

MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

Czyli tak jak moim przykładzie, muszę zrobić tablice graczy a później tworzyć na niej nowy socket?

Tak to ma wyglądać? Bo nie za bardzo chce działać.

Kopiuj
Socket socket = s.accept();
WatekGracza gracz[i] = new WatekGracza(socket, ++i);
gracz[i].start();
Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

o_O

Kopiuj
Map<Integer, WatekGracza> gracze = new HashMap<>();
//
WatekGracza gracz = new WatekGracza(socket, i);
gracze.put(i, gracz);
gracz.start();
i++;

I potem mozesz zrobić

Kopiuj
WatekGracza graczNumerX = gracze.get(X);
MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

Dziękuje za pomoc, a jeśli bym chciał wysłać wiadomość do gracza który otrzymał id 1.

Kopiuj
graczNumerX.out.println("Wiadomosc do Gracza 2");
Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

Jaja sobie robisz teraz? o_O Musisz w tej swojej klasie WatekGracza zaimplementować metodę która wysyła wiadomość za pomocą socketu...

MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

No ok, to nie problem, ale jak rozróżnić do którego socketu wysyłam wiadomość?

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

Nie rozumiem pytania. Przecież każdy WatekGracza ma JEDEN socket. Nic tam nie ma do rozróżniania. Każdy WatekGracza potrafi rozmawiać tylko z jednym, swoim graczem. Gdzie ty widzisz jakiś problem? o_O

MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

Powiedzmy, że mam taką sytuacje.
Jeśli serwer otrzyma wiadomość od gracza id:1 wtedy przesyła ją do gracza numer id:2.
Potrzebuje w socketcie gracza id:1 wysłać coś do socketu gracza id:2.
Jest to możliwe?

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

Piszesz aplikacje wielowątkową z komunikacją sieciową w javie nie umiejąc przy tym programować w Javie? Jak to jest w ogóle możliwe? o_O

  1. WatekKlienta 1 odbiera wiadomość.
  2. Przesyła ją do obiektu Serwera (więc wątek musi mieć referencje do serwera!) za pomocą jakiejś metody.
  3. Serwer wyciąga sobie z mapy WatekKlienta 2 i przekazuje mu wiadomość do przesłania
  4. WatekKlienta 2 ma metodę która za pomocą jego socketu przesyła wiadomość do odpowiedniego klienta.

Gdzie tu jest problem?

MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

no tylko jak ma wyglądać metoda z punktu 4?
Tylko to mi jest potrzebne.

Co do Javy, cały czas uczę się.

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

To teraz mi powiedz skąd wziąłeś ten kod u góry, bo sam go nie napisałeś...

Kopiuj
class WatekGracza extends Thread
{
    private final int numerGracza;
    private final Socket socket;
    private final PrintWriter out;
    private final BufferedReader in;
 
    WatekGracza(Socket socket, int nr)
    {
        this.socket = socket;
        numerGracza = nr;
        out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    }

    public void msgClient(String message){
        out.println(message);
    }
 
    public void run()
    {
        try { 
            int liczbaKlienta;
 
            String komunikat, odpowiedz="";
            while(true)
            {
                komunikat = in.readLine();
                System.out.println("Klient strzelił w:" + komunikat);
                liczbaKlienta = Integer.parseInt(komunikat);
                if(Server.ktosZgadl != -1)
                {
                    odpowiedz = "Przegrales, szybszy byl gracz numer " + Server.ktosZgadl;
                }
                else if(Server.liczba > liczbaKlienta) odpowiedz = "Za mało";
                else if(Server.liczba < liczbaKlienta) odpowiedz = "Za dużo";
                else if(Server.liczba == liczbaKlienta)
                {
                    odpowiedz = "Zgadłeś";
                    Server.ktosZgadl = numerGracza;
                }
                msgClient(odpowiedz);
            }
        } catch(Exception e) { e.printStackTrace();}
    }
}
MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

Kod bazowy miałem z książki, resztę sam dopisałem.
Ten kod w działaniu, nie różni się od mojego. Przynajmniej ja tak to widzę.

Obecnie wygląda to tak:
-Mamy do serwera połączonych dwóch graczy.
-Pierwszy gracz wysyła do serwera jakąś liczbę, powiedzmy 5.
-Serwer sprawdza warunki. Okazuje się, że spełnia się warunek serwera: "Server.liczba == liczbaKlienta"
-Serwer wysyła przez funkcję: "msgClient(odpowiedz);" wiadomość do gracza pierwszego: "Zgadłeś".

Ja chciałbym aby wyglądało to tak, żeby w ostatnim punkcie serwer wysłał wiadomość "Zgadłeś" do gracza numer dwa.

Mam już identyfikacje graczy, licznik (private int i), ale chciałbym by podczas wykonywania kodu pierwszego gracza, została wysłana wiadomość do gracza drugiego.

Strasznie mało przykładów z socketami w internecie.

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

Och no ale POMYŚL przez chwilę! Bo póki co to próbujesz "na pałe" coś zrobić... Twój problem nie jest z socketami tylko z brakiem myślenia.

  1. Zrób w klasie Serwer METODĘ "wygrał()" którą wątek klienta wywoła na serwerze kiedy ktoś zgadnie
  2. W tej oto metodzie niech serwer przeiteruje po wszystkich klientach i wyśle im, za pomocą "msg()" które pokazałem u góry, wiadomość jaką tam sobie chcesz.
MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

Ok w klasie serwer jest metoda która iteruje wszystkich klientów:

Kopiuj
    void wygrał()
    {
        for (int is=0; is<i; is++)
        {
            msgClient("Graczu "+is+", niestety wygrał ktoś inny");
        }
    }

Wywołuje ją gdy ktoś wygrał, tylko, ze ta wiadomość zostanie wysłana (jeśli graczy będzie dwóch) dwa razy do gracza który uruchomi metodę.
A nie do dwóch graczy.

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

Ja tu wcale nie widzę iterowania po klientach. Ja tu widzę jakieś iterowanie po liczbach z d**y. No i ciekawi mnie jak ty z serwera wołasz w ten sposób metodę msgClient skoro ona jest w WątkuKlienta. Ja proponuje jednak faktycznie iterować po klientach, np. za pomocą Map które pokazałem wyżej, a potem na każdym kliencie wywołać msgClient które za ciebie napisałem...

MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

Coś w tym stylu:

Kopiuj
Iterator<Integer, WatekGracza> keySetIterator = gracze.keySet().iterator();

while(keySetIterator.hasNext()){
  Integer key = keySetIterator.next();
  kay.msgClient("wygral ktos inny");
}

Poza tym, dziękuje, że masz do mnie taką cierpliwość. Naprawdę to doceniam to, że mi odpisujesz i pomagasz.
Dziękuje

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

Ty piszesz w javie 1.2 jakiejś?

Kopiuj
for(WatekGracza wg: gracze.keySet()){
    wg.msgClient("wygral ktos inny");
}
MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

przy pętli for otrzymuje taki błąd:
incompatible types: Integer cannot be converted to WatekGracza

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
2

@MaciekPaluch no to teraz tylko siąść i płakać! Bo po co zerknąć do dokumentacji albo pomyśleć? Kluczami są Integery a wartościami są Wątki. Więc nie keySet() tylko values() oczywiście...

MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

Podsumowywując

Klasa Server:

Kopiuj
Map<Integer, WatekGracza> gracze = new HashMap<>();

Metoda wygral:

Kopiuj
void wygral(){
for(WatekGracza wg: gracze.values()){
wg.msgClient("wygral ktos inny");
}}

W metodzie uruchom:

Kopiuj
while(true){
Socket socket = s.accept();
WatekGracza gracz = new WatekGracza(socket, i);
gracze.put(i, gracz);
gracz.start();
i++;}

Klasa WatekGracza:
Metoda msgClient:

Kopiuj
public void msgClient(String message){
out.println(message);
}

Nie pomieszałem niczego?

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

Jeśli działa to pewnie nie ;]

MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0

jeśli chce wywołać metodę wygrał w klasie WatekGracza, to muszę ją przekazać przez konstruktor, tak?

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
1

Metodę? o_O Niby się da, ale ja bym jednak przekazał referencje do Serwera ;]

MaciekPaluch
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 19
0
Kopiuj
Server.wygral();

tak nie mogę bo *wygral() *nie jest statyczna,
więc jak inaczej?

Shalom
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Space: the final frontier
  • Postów: 26433
0

Przekaz do wątku referencje do serwera!

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.