Einfache Client/Server-Kommunikation

Hackepeter

Aktives Mitglied
Servus,

wir haben derzeit ein Schulprojekt und müssen ein einfaches Spiel programmieren, welches auch im Netzwerk funktionieren soll. Allerdings kommen wir bei dem Thema Client/Server-Kommunikation an unsere Grenzen.

Wir haben keinerlei Ansätze zu dem Thema. Wir haben uns ein bisschen an einem YouTube Video und dieser Quelle orientiert.

Folgendes soll erfüllt werden:
  • Der Server muss mehrere Clients gleichzeitig verwalten können
  • Objekte müssen übertragen werden können (Spieler, Spielfeld, etc.)
  • Der Server wird in verschiedenen Fenstern benötigt (Anmelden, Mehrspieler-Spiel, Chat, etc.)

Ich kann ja mal zeigen, was wir bislang haben:

Java:
public class CServer
{
    
    private BufferedReader in = null;
    private PrintWriter out = null;
    private String incomingLine = null;
    private VServer serverView;
    private ArrayList<String> ipAllerClients = new ArrayList<String>();
    private Datenbank db = new Datenbank();
    private ServerSocket server = null;
    
    class InputThread extends Thread
    {
        private boolean running = true;
        public void run()
        {
            while(running)
            {
               try
            {   
                incomingLine = in.readLine();
                if(!incomingLine.isEmpty())
                {
                empfangen();
                
                
                }
            }
            catch (IOException e)
            {
                running = false;
               
            } 
            }
        }
        


    }

    public CServer(VServer p_serverView) throws IOException
    {
        System.out.println("Server");
        this.serverView = p_serverView;
        server = new ServerSocket(0);
        this.serverView.setTxtIpAddress(InetAddress.getLocalHost().toString() );
        this.serverView.setTxtPort(Integer.toString( server.getLocalPort() ) );
        while(true)
        {
            Socket clientSocket = server.accept();
            this.ipAllerClients.add(clientSocket.getInetAddress().toString());
            
            in=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            out=new PrintWriter(new OutputStreamWriter(
                    clientSocket.getOutputStream()));
            new InputThread().start();
            System.out.println(this.ipAllerClients.size());
            
        }
    }
    
    public void empfangen()
    {
        String[] stringProtokoll;
        stringProtokoll=incomingLine.split(";");
        switch (stringProtokoll[1])
        {
        case "login":
            anmelden(stringProtokoll);
            System.out.println(incomingLine);
            break;
        case "passwort":

            break;
        case "lobby":
            if(stringProtokoll[2].equals("chat"))
            {
                lobbyChatHinzufuegen(stringProtokoll);
            }
            

            break;
        case "spiel":

            break;
        case "status":

            break;
        case "spname":

            break;
        case "salt":
            saltHolen(stringProtokoll);
            
            break;
        case "offline":
            setClientOffline(stringProtokoll);
            break;

        }
    }
    


    public void lobbyChatHinzufuegen(String[] stringProtokoll)
    {
     String tmpName = stringProtokoll[3];   
     String tmpChat = stringProtokoll[4] ;  
     this.serverView.setChatModel(tmpName + " " + tmpChat);
     this.serverView.getListChat().repaint();
        
    }
    
    public void anmelden(String[] stringProtokoll)
    {
     String SendenProtokol;
     if( this.db.vglPasswort(stringProtokoll[2], stringProtokoll[3]) )
     {
      SendenProtokol = stringProtokoll[0] + ";login;true";  
      senden(SendenProtokol);
     
     }
     else
     {
      SendenProtokol = stringProtokoll[0] + ";login;false";  
      senden(SendenProtokol);
     }
    }
    
    
    public void saltHolen(String[] stringProtokoll)
    {
        String SendenProtokol;
        String tmpSalt = db.getSalt(stringProtokoll[2]);
        if(tmpSalt.length() == 10)
        {
        SendenProtokol  = stringProtokoll[0] + ";salt;" + tmpSalt;
        }
        else
        {
        SendenProtokol  = stringProtokoll[0] + ";salt;false";    
        }
        senden(SendenProtokol);
        
        
    }

    private void senden(String uebertragungsProtokoll)
    {
        this.out.println(uebertragungsProtokoll);
        this.out.flush();
        
    }
    
    
    private void setClientOffline(String[] stringProtokoll)
    {
       int index = this.ipAllerClients.indexOf( stringProtokoll[0] );
       this.ipAllerClients.remove(index);
       System.out.println(this.ipAllerClients.size()); 
    }
@Override
protected void finalize() throws Throwable
{
   
    this.server.close();
    in.close();
    out.close();
    super.finalize();
}
}
Wir würden gerne von vorne anfangen, da wir mit eigenen Objekten und nicht nur mit Strings arbeiten möchten, außerdem ist das ganze schon ziemlich unübersichtlich geworden.

Ich hoffe es ist nicht zu viel verlangt, wenn ich um ein kleines Client- und Serverbeispiel bitte, in dem auch andere Objekte als String übergeben werden. Das Tutorial auf java.sun.com ist wirklich verdammt kompliziert und wir treten quasi auf der Stelle und kommen nicht weiter.

Besten Dank im Voraus!

Gruß
 
Welche Probleme tauchen auf?

Was versteht ihr nicht bei dem Sun - Beispiel? Welches Beispiel ist gemeint?

Ansonsten finden sich zu dem Thema mehr als nur ein Beispiel. Da muss man vielleicht mal 2 Minuten googeln und 2 Minuten Zeit investieren.
 
Für das Senden von Objekten verwendet ihr dann einfach nen ObjectOutputStream anstatt einem PrintWriter, und nen ObjectInputStream statt dem BufferedReader.
 
Ja, wenn du mehr als nur ein Beispiel findest, kannst du ja gerne mal etwas verlinken, was bei bei den genannten Aspekten hilft. Den Usern zu unterstellen, dass sie unfähig sind, um vernünftig zu recherchieren ist immer leicht getan. Das genannte Beispiel ist über dem Code bereits verlinkt!

Wir haben keine Ahnung von dem Aufbau. was genau ist vernünftig? Wie kann man so etwas sehr simpel aufbauen? Welche Komponenten werden benötigt?

Wir haben uns folgendes Konzept überlegt: Jeder Client bekommt auf dem Server einen eigenen Thread. Wenn nun ein Mehrspieler-Spiel gestartet wird, wird ein weiterer Thread für dieses Spiel erzeugt, der die beiden andere Threads miteinander kommunizieren lässt.

Wie kann man sowas umsetzen??
 
Eure Rechersche ergab ein Youtube film?

Die Idee mit dem Thread und so ist ja schon richtig und wird mehrfach als Beispiel genannt.

Aber "Wie kann man das umsetzen". Was soll man hier als Antwort nennen? Quellcode wird hier sicher keiner posten.
 
Mit deiner letzten Aussage hast du nicht recht. Es gibt genug Leute, die weniger nörgeln und einfach hilfsbereit sind. Ich bin nicht hier, damit mir jemand erklärt, dass ich unfähig bin, Recherche zu betreiben und ich bin auch nicht hier, um zu lesen, dass andere User hier mit Sicherheit keinen Quellcode posten werden. Woher weißt du das so genau? Kannst du in die Köpfe von allen Usern hineinsehen?

Wie auch immer. Threads sind der richtige Weg, das haben wir ja soweit begriffen. Ist es auch richtig, dass jede Connection einen eigenen Thread erhält? Die Frage ist halt, wie die Threads untereinander aufeinander zugreifen können. Über Server-Klassenattribute ja vermutlich eher weniger, da diese dann ja von verschiedenen Benutzern verwendet werden.
 
Jeder Client bekommt auf dem Server einen eigenen Thread.
Eventuell war die Aussage auch nur unglücklich formuliert, aber nicht der Client bekommt einen eignenen Thread, sondern das Lesen vom Inputstream des Clients passiert in einem separaten Thread. Also der Server nimmt die Verbindung von Client an, holt sich den Inputstream des Client Sockets und startet einen Thread in dem er von diesem Stream blockierend liest. Um später dem Client "antworten" zu können muss er diesen bzw. bestimmte Element (wie z.B. OutputStream) in einer Liste o.ä. halten.
 
Eventuell war die Aussage auch nur unglücklich formuliert, aber nicht der Client bekommt einen eignenen Thread, sondern das Lesen vom Inputstream des Clients passiert in einem separaten Thread. Also der Server nimmt die Verbindung von Client an, holt sich den Inputstream des Client Sockets und startet einen Thread in dem er von diesem Stream blockierend liest. Um später dem Client "antworten" zu können muss er diesen bzw. bestimmte Element (wie z.B. OutputStream) in einer Liste o.ä. halten.

Ich würde mir mal das NIO ansehen, denn das ganze wird Serverseitig sehr unübersichtlich und verzwickt wenn jeder Client einen eigenen Thread bekommt. Mit dem NIO kannst du ganz einfach ein MAIN-Thread starten welcher alle Clients der reihe nach abfragt und ggf. einkommendes überprüft und/oder weiterleitet. Solltest du dennoch für jeden Clienten einen Thread erstellen wollen (ohne NIO halt) solltest du gut synchronisieren.
 
NIO rastet aber schon ein bisschen aus, oder? Das wirkt auf den ersten Blick absolut komplex. Bin froh, dass wir mit Threads klarkommen! Also nochmal: Wie kommunizieren Threads miteinander?
 
Wie die kommunizieren?

in einem thread kommen daten an, server wertet es aus und schickt es vermutlich an alle anderen wieder raus.

man kann übrigends auch beliebige objekte einfach als strings verschicken, mein erstes spiel mit netzwerk damals hab ich auch einfach über den versand von zeichenketten gelöst.
 
Also nochmal: Wie kommunizieren Threads miteinander?

Brauchen sie nicht. Du musst alle Clients die connected sind an einer Stelle vermerken, die von allen Threads zugänglich ist. Eine Statische ArrayList z.B.

Wenn nun also bei Thread-3 etwas ankommt, brauchen Thread-1 und 2 garnichts davon wissen. Thread-3 wertet es nun einfach aus und schickt es an alle Clienten zurück.
 
Woher weißt du das so genau? Kannst du in die Köpfe von allen Usern hineinsehen?

Naja ich lese das Forum seit ein paar Tagen. Nach 10 Stunden hat immernoch keiner Code gepostet ;D. Ich glaube Du musst schon damit anfangen.

---

Ich glaube dir fehlt hier eine kleine Vokabel "Conurrent".

Google: "Concurrent Server java" => 6,9 Millionen. Sollten hier youtube Quellen kommen, einfach skippen.

NIO ist hierfür nicht so gut geeignet. Man sollte schon wissen, was man hier macht, bevor jemand anders es für einen macht.

Fang erstmal klein an. 1 Client und 1 Server beides auf einer Maschine. Das ist schwer genug.
 
Danke für eure Hinweise, das hat uns systematisch weitergeholfen. Objekte können wir nun problemlos übergeben, besten Dank. An den einzelnen Threads sitzen wir derzeit noch, aber es sieht soweit ganz vernünftig aus.
 

Neue Themen


Zurück
Oben