Problem mit der Client Server

Status
Nicht offen für weitere Antworten.

SchachFritz

Aktives Mitglied
Guten Tag.

Ich bin zur Zeit dabei ein Spiel das über LAN spielbar sein soll zu programmieren. Dazu muss übers Netzwerk ein Objekt, das den aktuellen Spielstand charakterisiert übers Netz verschickt werden. Diese Klasse habe ich schon erstellt. Ich habe jedoch Probleme was die Client-Server Architektur angeht. Ich habe bisher eine methode set geschrieben, die das Objekt vom Client auf den Server überträgt. Auf dem Server wird diese Objekt mit einer globalen Variable referenziert. Auf dem Client gibt es ausserdem eine Methode get, die dieses Objekt vom Server zum Client sendet. Ich habe für das ganze Socket benutzt. Um sicherzustellen, dass jedesmal nur einer auf den Stream schreibt, habe ich eine variable Busy genommen, die anzeigt ob gelesen oder geschrieben werden kann.

Auf dem Server habe ich also, für jeden Client einen Thread. Auf dem Client, habe ich ein Thread das alle drei Sekunden die get Funktion aufruft. Dafür habe ich eine while(true) in Verbindung mit sleep benutzt.
Um nun die set funktion zu benutzen wird dann die boolean variable Busy auf true gesetzt. In der while Schleife des Threads wird getestet Busy getestet, falls dies true ist, so wird nicht gelesen. Das gleiche gilt auch fürs Schreiben.

Nun auf den ersten Blick funktioniert dies auch. Allerdings treten dabei ein paar Probleme auf:
- dies bedeutet einen ünnötigen Trafik auf dem Netzwerk, da alle drei Sekunden der Client eine Anfrage macht, und der Server darauf antwortet
- kann durch diese drei Sekunden Intervalle, das spiel nicht richtig synchronisiert werden, d.h. verschiedene Clients,bekommen den aktuellen Spielstand erst viel später als andere.

Die optimale Architekur wäre, wenn ein Client jedesmal wenn er gespielt hat, die set Methode benutzt. Der Server referenziert wieder das Objekt, sendet es aber dann sofort an alle Clients, ohne dass die einen Anfrage gemacht habe. Allerdings habe ich da ein paar Probleme, was das Schreiben und Lesen auf dem Stream betreffen. Kann mir jemand erklären, wie ich da verhindern kann das ein Client gleichzeitig auf dem Stream schreibt und liest? Das gleiche Problem befindet sich ja auch auf dem Server. Das grösste Problem was ich habe ist, dass die Spieler nicht nach ein ander spielen müssen. Dies bedeutet, dass es möglich ist, dass der Server während der das Objekt an alle Clients sendet, ein Client versuchen wird ein neues Objekt zum Server zu senden.

Ich habe ein wenig mit google gesucht, und da die Methode available() gefunden. Kann man damit herausfinden, ob bereits auf dem Stream gelesen oder geschrieben wird?

Ich hoffe Ihr könnt mich in dieser Sache beraten.

Vielen Dank im Voraus.
MfG
 
T

tuxedo

Gast
Hmm, du musst da eindeutig eine Synchronisation einbauen und die verteilung der Daten dem Server ueberlassen....Polling beim Client funktioniert ja nicht wie du bereits richtig erkannt hast.

Was ich noch nicht verstehe ist das "verhindern kann das ein Client gleichzeitig auf dem Stream schreibt und liest" ...
Wuerde das so machen (vllt naiver Ansatz -> untested):

Sofern immer nur ein Client zu einer Zeit dem Server seinen Spielstand mitteilen darf:
Dem Server ein Flag geben das anzeigt ob gerade jemand schreibt. D.h. wenn ein Client Daten zum Server sendet muss der Client erst dieses Flag abfragen. Wenn dieses Flag sagt "alles klar, keiner schreibt" sendet er. Der Server muss waehrend dessen das Flag auf "belegt" umschalten. Andere Clients duerfen somit gerade nicht schreiben und muessen sich in eine Warteschleife begeben und es nach einer Zeit X nochmal probieren.
Ist der Client der gerade geschrieben hat fertig muss der Server sein Flag wieder auf "frei" umschalten. Die anderen Clients koennen dann so nacheinander ihre Daten abgeben..

Problem bei diesem Ansatz:
Unter ganz dummen Umstaeden kann es sein dass ein Client NIE dran kommt mit senden.. In diesem Falle koennte man sowas wie eine Wartenummer vergeben. Client fraegt an ob er senden darf... Server sagt belegt und gibt ihm eine Wartenummer die die Reihenfolge der Sendeerlaubnis darstellt.

Mit dem updaten der Clients vom Server:
Lasse beim Client einen Thread laufen der nach update-Nachrichten vom Server wartet. Jedesmal wenn ein Client seinen Spielstan dem Server mitgeteilt hat schickt der Server an alle gelisteten Clients die aktuelen Spielstaende...

Ist alles nur mal so kurz zusammengedacht und es gibt mit Sicherheit eine bessere Loesung: Try & Error...

greets
Alex
 

SchachFritz

Aktives Mitglied
Danke für deine Hilfe.
Ich habe da folgendes erstellt:
ich habe auf derm Sever eine variable, die ich ganz passend Read genannt habe, die jedesmal auf true gesetzt wird, wenn der Server lesen soll. Falls der Server was schreiben muss, so wird Read auf false gesetzt. Das habe ich auch auf dem Client erstellt.

Allerdings habe ich das Problem, dass nach in.readObject(), der ganze Thread t blockt und ich somit nach Read=false zwar eigentlich im Hauptthread schreiben könnte, der Thread T aber immer noch versucht zu lesen.
Nun zu meiner Frage

Kann ich irgendwie die methode in.readObject() unterbrechen?
 
T

tuxedo

Gast
SchachFritz hat gesagt.:
Danke für deine Hilfe.
Ich habe da folgendes erstellt:
ich habe auf derm Sever eine variable, die ich ganz passend Read genannt habe, die jedesmal auf true gesetzt wird, wenn der Server lesen soll. Falls der Server was schreiben muss, so wird Read auf false gesetzt. Das habe ich auch auf dem Client erstellt.

Allerdings habe ich das Problem, dass nach in.readObject(), der ganze Thread t blockt und ich somit nach Read=false zwar eigentlich im Hauptthread schreiben könnte, der Thread T aber immer noch versucht zu lesen.
Nun zu meiner Frage

Kann ich irgendwie die methode in.readObject() unterbrechen?

Versteh ich nicht ganz...
Nochmal zum vrstaendnis:

Die hast fuer jeden client auf dem Server einen Thread. Jeder Thread hat zugriff auf eine boolsche Variable, nennen wir die "busy".
Diese Variable steht standardmaessig auf "false". Das heisst "Server ist nicht beschaeftigt".

Sendet ein Client seinen Spielstand an den Server, sprich, wurde ein Object mittels readObject gelesen wird das busy-flag auf TRUE gesetzt. Andere Clients koennen jetzt nichts senden. Der Server verarbeitet jetzt nun den Spielstand und schickt noetige Informationen an die Clients (die passende Empfangsthreads haben). Sobald er alle Informationen an die Clients verschickt hat wird das busy-Flag wieder zurueckgesetzt.

readObject ist "blockierend" und laesst sich meines wissens nicht "unterbrechen" (korrigiert mich bitte jemand wenn ich Muell erzaehle).
Problem bei meinem Ansatz ist dass erst nach dem empfangen eines Objectes vom Client der server nachschauen kann ob jemand anders gerade seinen Spielstand abliefert. In diesem Fall wird es zwangslaeufig irgendwann vorkommen dass

1) Ein client seinen Spielstand gesendet hat und der Server diesen gerade arbeitet. Er ist somit beschaeftigt und kann waehrend dessen nix anderes tun (um inkonsistenz zu vermeiden).
2) Andere Clients die gerade ihren Spielstand abliefern senden diesen zum Server. Da readObject blockierend kann der Server erst nach einem erfolgreichen readObject nachschauen ob er den Spielstand gleich verarbeiten kann. Somit koennen mehrere Spielstaende gleichzeitig in am Server eintreffen und koennen nicht sofort verarbeitet werden.
3) Ist der erste Client der die verarbeitung anderer Spielstaende blockiert hat fertig wird das Flag wieder auf false gesetzt. Somit koennten die anstehenden Spielstaende verarbeitet werden. ABER: es stehen ja mehrere an. Wer darf zuerst ?

Ich denke du muesstest mal erklaeren wie das mit deinen Spielstaenden funktioniert:
Kommt es zu inkonsistenzen wenn der Server in mehreren Threads gleichzeitig Spielstaende verarbeitet ?

- Alex
 

SchachFritz

Aktives Mitglied
Erstmal danke für deine Hilfe. Es ist jedesmal nur einer der Clients der den Spielstand sendet. Allerdings können sämtliche Clients zur jeder Zeit ein "Exit" schicken.
Bei ankunft des exits an den Server, wird dieser die Socketverbindung schliessen. Danach sendet er das exit an alle anderen Clients. Diese werden dann wiederum eine Message anzeigen und dann auch ein exit an der Server senden.

Was allerdings den Spielstand anbelangt kann also keine Inkonistenz auftreten. Jedoch kann es sein, dass der Client der gerade den Spielstand sendet auch ein Exit senden muss (wegen dummheit des Users). In der Version die ich vorher hatte, hat dies einwandfrei funktioniert. Allerdings sendet der Client ja dafür auch jede 3 Sekunden eine Anfrage an den Server. Ich will aber den Trafik auf dem netz verringern.

Code auf dem Client
Code:
class Updater implements Runnable
   {public boolean hastoRun = true;
       public void run()
       {
           while (hastoRun)
           { while (Read)
               try {
               
             Object obj=null ;              
               
                   obj=in.readObject();
                   System.out.println("Object readed");
                  
                   if (obj!=null){ System.out.println("Received partie");getPartie((packet) obj); }
                   else System.out.println("Partie £=null");
               }
      
           
                   
               
               
           catch (Exception Ex){System.out.println(Ex.toString());}}
            
           



       }
   }

   public void sendPartie(Partie partie)
   {
       
      
       Read = false;
       
       try{  in = null;
           
} catch(Exception ex){}
   
       System.out.println("Sending partie");

       packet toSend = new packet(Command.UPDATE_PARTIE,partie);
       System.out.println("Ok.. busy1");
       try {out.writeObject(toSend);out.flush();System.out.println("Wrriten to sefver"); out.close();  in = new ObjectInputStream(myclient.getInputStream());}
       catch (Exception Ex)
       {
        JOptionPane.showMessageDialog(null, CANNOT_SEND + Ex.toString(), "Erreur de connexion", JOptionPane.ERROR_MESSAGE);
        sendExit(null);
       }
       Read=true;
      

   }

Meine Idee war, dass der Client das lesen nur unterbrechen muss, wenn er etwas senden will. Das Problem ist jedoch, das wenn er bereits beim readObjekt angelangt ist, so ist der Thread ja blockiert. Und kann nicht mehr testen ob er lesen soll oder nicht.

Auf dem Server habe ich folgendes:



Code:
 public void handleClient(Socket socket)
    {
        ObjectInputStream in = null;
        ObjectOutputStream out = null;
        boolean hastorun =true;
        try{
          in = new ObjectInputStream(socket.getInputStream());

      }
      catch (Exception ex) {display(CANNOT_SEND);}
       InetAddress client_address = socket.getInetAddress();

        display(NEW_CONNECTION+ client_address.getHostAddress());

       packet pa = null;
       Object ob = null;
       broadCast();
       while (hastorun){

           try {
               while (Read){
              ob=in.readObject();

               if (ob!=null){
               display("Getting command .... " + client_address);
               pa=(packet) ob;
               if (pa.getCOMMAND()==Command.UPDATE_PARTIE) {Actual= pa;broadCast();}
....
Code:
public void broadCast()
      {
          Read=false;
         
          display("Broadcasting");
          for (int i =0;i<clients.size();i++)
          {
              Socket sock = (Socket) clients.get(i);
             try{ ObjectOutputStream out = new ObjectOutputStream(sock.getOutputStream());
                 InetAddress adress = sock.getInetAddress();
                 display("Writing to  " + adress.getHostAddress());
                 out.writeObject(Actual);
                 out.flush();
                 display("Writing completed.. searching next client.");

             }
             catch(Exception Ex) {display("Broadcast error");}
          }
          display("Broadcast completed");
          Read=true;
   


      }

Kann mir jemand veraten wie ich meine Idee umsetzen kann.

Danke
 
T

tuxedo

Gast
Korrigier mich wenn ichs schon wieder falsch verstanden habe.. Aber dein Problem besteht nur darin dass es zu komplikationen kommt wenn jemand ausversehen auf EXIT geklickt hat?

In deinem HandleClient hast du glaub auch nen Fehler drin.. Du hast ne While-Schleife deren Bedingung "read" ist...
So wie ich das verstehe waere ein "if (read)" geschickter.

Aber wenn das gleichzeitige senden der Spielstaende von den Clients eh keine Inkonsistenzen macht koennen wir uns das READ an dieser Stelle sparen.


Ich hab nochmals deinen ersten Thread durchgelesen. Alle X Sekunden fraegen die Clients den Server nach Spielstaenden anderer Clients? Seh ich das richtig ? Im Code find ich das nicht, oder hast du das schon geaendert...

Ich glaub wir muessen mal alles unnoetige "rauskuerzen" damit wir wieder auf einen Nenner kommen :)

- Alex
 

SchachFritz

Aktives Mitglied
Es kann sein dass ich das mit den Sockets falsch verstanden habe. Aber soweit ich weiss, kann man nicht gleichzeitig auf den Stream schreiben und lesen. Daher wollte ich die if oder while (Read) haben, damit der Thread weiss ob er lesen soll oder nicht.
Da ja manchmal dieMethode sendPartie auf den Stream schreiben muss setzt sie Read auf false, somit soll der Thread Updater ja dann aufhören auf dem Stream zu lesen. Anschliessend kann sendPartie ein Objekt senden und dann Read wieder auf true setzen, und der Thread Updater kann wieder mit lesen anfangen.

Das Problem bei dem ganzen ist ja, wenn sendPartie Read auf false setzt, so ist der Thread Updater meistens bereits wegen dem readObjekt blockiert und kann garnicht testen, ob er überhaupt noch lesen soll. Denn er wird auch nichts vom Server gesendet bekommen, da er es ist der senden soll.

Denn der Server liest ja auch und wartet darauf dass ein Client was sendet. Anschliessen sendet der Server es an alle Clients. Ergo, wird der Client auch nichts vom Server bekommen. Beide lesen also auf dem selben Stream ohne, dass irgendwas gesendet wird.


EDIT:

Eine Möglichkeit wäre, dass wenn die Methode sendPartie etwas schreiben will, dass dann der ganze Thread Updater gestoppt wird. Jedoch wäre dies nicht besonders sauber.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
G Server-Client IO Problem Netzwerkprogrammierung 6
A Problem beim Senden von Client zu Server Netzwerkprogrammierung 10
B Client/Server Connection Problem Netzwerkprogrammierung 2
M Problem Client - Server Sockets: .ready() wird nie true! Netzwerkprogrammierung 6
X Problem mit Server-Client-Kommunikation Netzwerkprogrammierung 14
K Client - Server Problem Netzwerkprogrammierung 16
T RMI Problem Client-Server Netzwerkprogrammierung 2
J Socket Client - Server Problem Netzwerkprogrammierung 4
D Client Server Problem, Methode readline() löst SocketException "Connection reset" aus Netzwerkprogrammierung 8
J Client server problem Netzwerkprogrammierung 3
S Problem bzgl. Sockets / Server-Client-Struktur Netzwerkprogrammierung 3
N Socket Java server c# client problem Netzwerkprogrammierung 7
K Problem Performance Client-Server Netzwerkprogrammierung 5
W Problem mit Server/Client mit ObjectOutputStream Netzwerkprogrammierung 5
S Client-Server Chat Problem nur im lokalen Netztwerk Netzwerkprogrammierung 23
K Client-Server Problem Netzwerkprogrammierung 2
G Problem mit Client-Server Kommunikation Netzwerkprogrammierung 4
S Client/Server Problem Netzwerkprogrammierung 2
A Client Server Problem Netzwerkprogrammierung 37
G Problem bei Objekt senden von server zu client Netzwerkprogrammierung 6
L ganz ganz einfach Client/Server [Problem] Netzwerkprogrammierung 2
R Java Applikation als Client ,Servlet als Server: Problem? Netzwerkprogrammierung 3
V Client Server Problem, empängt oder sendet nichts Netzwerkprogrammierung 4
M HttpUrlConnection + Client/Server Problem Netzwerkprogrammierung 2
S Habe ein Problem mit Sockets -> Client Server Netzwerkprogrammierung 2
G Datenautausch Client/Server , hab da ein kleines problem Netzwerkprogrammierung 3
M Socket Chat-Client-Problem Netzwerkprogrammierung 8
0din SMTP Client - readline problem Netzwerkprogrammierung 4
C Problem mit RMI-Client Netzwerkprogrammierung 11
DamienX Chat Socketserver/Client. wo ist das Problem? Netzwerkprogrammierung 2
I Apache http-client: Problem beim Proxyaufruf Netzwerkprogrammierung 2
S RMI Chat Problem, Client bekannt machen Netzwerkprogrammierung 2
I Socket Problem mit den WebSocket Antworten der Discord API Netzwerkprogrammierung 0
K Java Websocketserver Problem | Android to Pi Netzwerkprogrammierung 1
C RMI Produzent-Verbraucher-Problem - Code review Netzwerkprogrammierung 12
B Socket Bilder verschicken via Sockets. Heap-Problem. Netzwerkprogrammierung 2
S Problem bei dem Bluetoothverbindungsaufbau Netzwerkprogrammierung 2
M Netty - TCP Problem Netzwerkprogrammierung 4
L Socket Problem mit Server Netzwerkprogrammierung 1
J Chat Server starten über GUI problem Netzwerkprogrammierung 4
M Problem bei Socket (MultiplayerSpiel) Netzwerkprogrammierung 4
M Socket CDI, Websocket reference Problem ! Netzwerkprogrammierung 2
Shams Problem mit Eventbus in Verbindung mit Server Netzwerkprogrammierung 0
G apache httpClient Problem. Netzwerkprogrammierung 5
H Problem mit ObjectStreams Netzwerkprogrammierung 3
D Socket BufferedWriter/Reader Problem Netzwerkprogrammierung 1
Maxim6394 Problem mit Socks5 Implementierung Netzwerkprogrammierung 0
C Handle Connection Problem Netzwerkprogrammierung 3
E HttpUrlConnection Cookie Problem Netzwerkprogrammierung 0
X Problem mit vielen Bytes über Socket Netzwerkprogrammierung 23
O 4Gewinnt Multiplayer - Netzwerk Problem (TCP) Netzwerkprogrammierung 1
A Socket Socket-Problem - Object wird nicht übertragen Netzwerkprogrammierung 3
R Problem beim Programmieren eines Chatprogramms Netzwerkprogrammierung 5
E einfaches Problem: Session-Handling bei Servlets Netzwerkprogrammierung 5
G Problem mit einem FileWatcher Netzwerkprogrammierung 7
T Socket Server starten Thread Problem Netzwerkprogrammierung 12
G Problem mit STATIC-Verständnis Netzwerkprogrammierung 8
S Umstellung AS400 auf Postgre - Problem beim Arbeiten mit Metadaten Netzwerkprogrammierung 2
J Facelets Include Rendered Problem Netzwerkprogrammierung 2
J Socket Problem mit C++/Java Netzwerkprogrammierung 20
P Problem mit Datagram-Sockets Netzwerkprogrammierung 2
G Socket NIO2 Problem mit AsynchronousSocketChannel beim Schließen Netzwerkprogrammierung 3
G Cookie Verwaltungs Problem nach Login auf InetSeite (Wo utma-Cookie?) Netzwerkprogrammierung 18
C Socket Problem mit ObjectInput/OutputSream Netzwerkprogrammierung 7
B Socket Problem mit Netzwerkchat Netzwerkprogrammierung 21
D RMI Problem beim shutdown von verteilter CORBA-Anwendung Netzwerkprogrammierung 6
Maxim6394 ipv6 Problem Netzwerkprogrammierung 2
Maxim6394 Proxyserver Performance Problem Netzwerkprogrammierung 11
C Socket Problem mit ObjectInput/OutputSream Netzwerkprogrammierung 5
B RMI und Problem mit rmic-Tool Netzwerkprogrammierung 3
C FTP storeFileStream Problem Netzwerkprogrammierung 3
N Problem über http eine Datei zu senden Netzwerkprogrammierung 4
D JavaMail - Mailsabrufen Problem (imap) Netzwerkprogrammierung 12
J HTTP Übersetzung yahoo babelfish - Zeichensatz-Problem Netzwerkprogrammierung 6
D Apache CXF, JAX-WS Problem bei Arrays - einfacher Server Netzwerkprogrammierung 2
M Problem beim Datenempfang Netzwerkprogrammierung 2
M Problem mit Socket-Verbindung Netzwerkprogrammierung 2
N NIO Problem beim speziellen Behandeln von einzelnen Benutzern Netzwerkprogrammierung 13
D Thread problem Netzwerkprogrammierung 3
T Servlets JSP: Tomcat Problem Netzwerkprogrammierung 4
P RMI Stub Problem Netzwerkprogrammierung 3
D Socket UDP Übertragungs Problem Netzwerkprogrammierung 7
I HTTP Post aus html in Java einlesen - Problem Netzwerkprogrammierung 2
I HTTP Post aus html in Java einlesen - Problem Netzwerkprogrammierung 6
D Problem mit ObjectInputStreams Netzwerkprogrammierung 10
D Socket Problem mit InputStreamReader Netzwerkprogrammierung 3
N CRC32 CheckSum Problem bei UDP Netzwerkprogrammierung 2
V Java Mail Api - IMAP Problem Netzwerkprogrammierung 6
P RMI Problem Netzwerkprogrammierung 4
I Problem bei Outputstreamerzeugung in anderer Klasse als Socket Netzwerkprogrammierung 5
S Socket Problem mit Objektübertragung Netzwerkprogrammierung 16
Shoox Reader / Writer Problem Netzwerkprogrammierung 2
S Problem mit 2 Serversockets unter Win XP Netzwerkprogrammierung 7
P Socket Problem mit Netzwerkverbindung über TCP Netzwerkprogrammierung 12
M RMI - Connection Problem Netzwerkprogrammierung 7
E HTTP Problem beim Auslesen von Websiten Netzwerkprogrammierung 6
T Problem bei Findung der richtigen Architektur Netzwerkprogrammierung 3
AlexSpritze Authentication Problem bei WebServices Netzwerkprogrammierung 4
J Socket Problem -Proxies Netzwerkprogrammierung 2
R HTTP Problem bei Authentifizierung über (Http)UrlConnection Netzwerkprogrammierung 2

Ähnliche Java Themen

Neue Themen


Oben