Jak przeskoczyć do innego wątku

Jak przeskoczyć do innego wątku
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • 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:ponad 12 lat
  • Ostatnio:ponad 4 lata
  • 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:ponad 21 lat
  • Ostatnio:około 3 lata
  • 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.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • 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:ponad 21 lat
  • Ostatnio:około 3 lata
  • 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);

"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 2x, ostatnio: Shalom
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • 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:ponad 21 lat
  • Ostatnio:około 3 lata
  • 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...


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • Postów:19
0

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

Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • 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


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • 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:ponad 21 lat
  • Ostatnio:około 3 lata
  • 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?


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • 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ę.

edytowany 1x, ostatnio: MaciekPaluch
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • 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();}
    }
}

"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • 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:ponad 21 lat
  • Ostatnio:około 3 lata
  • 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.

"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 1x, ostatnio: Shalom
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • 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.

edytowany 2x, ostatnio: MaciekPaluch
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • 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...


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • 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:ponad 21 lat
  • Ostatnio:około 3 lata
  • 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");
}

"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • Postów:19
0

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

Zobacz pozostałe 5 komentarzy
niezdecydowany
niezdecydowany
fuuuj - co klniesz, panie ! kultury trochi
niezdecydowany
niezdecydowany
AVE
azalut
c# nowe przekleństwo jawowców :D
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • 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...


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
Wizzie
nie ma to jak zrzucić swój błąd na kogoś :D
Shalom
Na nikogo nic nie zrzucam. Błąd był mój, ale ja posta pisałem "z palca" i dlatego go przeoczyłem. Autor ma pod ręką IDE i przecież od razu widać o co chodzi.
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • 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?

edytowany 1x, ostatnio: MaciekPaluch
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
1

Jeśli działa to pewnie nie ;]


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • Postów:19
0

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

Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
1

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


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
MaciekPaluch
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 10 lat
  • Postów:19
0
Kopiuj
Server.wygral();

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

Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Przekaz do wątku referencje do serwera!


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
panryz
@Shalom coś Ty się NervoStopu nawpierdzielał ?

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.