Threads & Streams

JUserToto

Aktives Mitglied
Hallo zusammen,

ich wage mich heute zum ersten Mal richtig an die Netzwerkprogrammierung, komme aber nicht so richtig weiter.

Zum Einstieg wollte ich ein kleines Spiel schreiben. Die Struktur sollte wie folgt ablaufen:

Der Server läuft im Hintergrund und wird zu Beginn gestartet.
Er läuft in einem Thread. In der run() wird zyklisch socket = server.accept(); aufgerufen, damit er ständig Verbindungen annehmen kann.

Im Spiel soll nun z.B. jede Sekunde ein Datenabgleich mit dem Server gemacht werden. Es läuft also ein Thread, der jede Sekunde die Spieldaten vom Server läd.

Hier mal die Codes (auf das Wichtigste beschränkt, so also nicht lauffähig):

Server:

Java:
public class ServerRunnable implements Runnable {

    private ServerSocket server;
    private Spiel spiel;
    private Socket socket;
    private ObjectInputStream in;
    private ObjectOutputStream out;

    public ServerRunnable() throws IOException {
            spiel = new Spiel();
            server = new ServerSocket(57070);
    }

    @Override
    public void run() {
        while (true) {
                socket = server.accept();
                
                out = new ObjectOutputStream(socket.getOutputStream());
                in = new ObjectInputStream(socket.getInputStream());
                
                Object input;
                if ((input = in.readObject()) != null) {
                    if (input instanceof Integer) {
                        Integer serverCode = (Integer) input;
                        if (serverCode.equals(ServerCodes.GIB_SPIEL)) {
                            out.writeObject(spiel);
                        }
                    }
                }            
        }
    }

Client:

Java:
    @Override
    public void run() {
        while (true) {
             Thread.sleep(1000);
             this.spiel = gibSpiel();
        }
    }

    public Spiel gibSpiel() {
        Spiel spiel = null;

        out =  new ObjectOutputStream(this.serverSocket.getOutputStream());
        out.writeObject(ServerCodes.GIB_SPIEL);
        out.flush();

        in = new ObjectInputStream(this.serverSocket.getInputStream());
        spiel = (Spiel) in.readObject();

        return spiel;
    }

Der erste Aufruf von gibSpiel() liefert den gewünschten Erfolg. Es wird ein gültiges Spiel zurück gegeben. Beim zweiten Aufruf blockiert "new ObjectInputStream(this.serverSocket.getInputStream());"
den Thread, es wird also weder der Code gesendet, noch ein Ergebnis empfangen.

Funktioniert diese Strategie generell nicht oder hab ich die Client-Server Kommunikation noch nicht verstanden?

Danke für Antworten :)

edit: "Spiel" könnte übrigens besser "Spieldaten" heißen. Das sind Daten wie z.B. die Positionen der Spieler.

lg Toto
 
Zuletzt bearbeitet:

Bizarrus

Bekanntes Mitglied
Was mich ein wenig irritiert: Warum wird "jede Sekunde" geprüft ob Daten vorhanden sind?
Du nutzt doch ein Socket. Sobald Daten vorhanden sind, werden die doch verarbeitet. Da brauchst du nicht manuell sagen "jede Sekunde" - Dies geschieht automatisch.

Wenn der Client etwas sendet, wird dies direkt vom Server ausgeführt. Andersherum ebendso.

Du hast, wie du bereits schreibst, dies noch nicht ganz verstanden.
Der Blockiert aus dem Grund, weil du bei socket.accept() kein Thread benutzt.

Ich schreib dir da gleich mal ein wenig Source, dauert aber noch 1-2 Stunden, da ich leider noch an einem Kundenprojekt sitze.
 
Zuletzt bearbeitet:

JUserToto

Aktives Mitglied
Hallo,

danke für die Antwort. Ich studiere Informatik, aber in Sachen Netzwerkprogrammierung haben wir leider noch garnix gemacht (5. Semester) :(

Im Moment versteh ich es so:

Der Server verwaltet die Spieldaten (d.h. die Positionen der Spieler, Punkte etc.), weil diese für alle Spieler im Netzwerk identisch sein müssen.

Man kann zuvor im Menü einen Server eröffnen und diesem (oder einem externen) beitreten.

Der Client muss also irgendwie an die Daten des Servers "ran kommen". Praktisch gesehen: Die GUI will den Spieler abbilden und brauch die Koordinaten. Sie fragt also den Server nach den Koordinaten.
Oder soll etwa der Server das neuzeichnen veranlassen, wenn er neue Koordinaten bekommt? Dann müsste der Server alle seine Clienten kennen und die größte Arbeit übernehmen?
 

Bizarrus

Bekanntes Mitglied
So, hier mal nun ein Beispiel:
Der Server akzeptiert jeden Clienten und setzt diesen in ein Thread-Objekt:
Java:
public void run() {
	        while (true) {
	        	try {
					socket = server.accept();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
					
	            new Client(socket, spiel).start();     
	        }
    }

Und jeder Client ist dann über eine Klasse instanziert:
Java:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Client extends Thread implements Runnable {
	protected Socket s;
	protected Spiel game;
    private ObjectInputStream in;
    private ObjectOutputStream out;
	
	Client(Socket sock, Spiel game) {
		this.s = sock;
		this.game = game;
	}
	
	@Override
	public void run() {
		try {
			out = new ObjectOutputStream(s.getOutputStream());
			in = new ObjectInputStream(s.getInputStream());
	        
	        Object input;
	        if ((input = in.readObject()) != null) {
	            if (input instanceof Integer) {
	                Integer serverCode = (Integer) input;
	                if (serverCode.equals(ServerCodes.GIB_SPIEL)) {
	                    out.writeObject(this.game);
	                }
	            }
	        }
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
         
	}

}

Die ganzen Clients könntest du nun noch in einer HashMap (o.ä.) beim Server mit hereinsetzen, damit du vom Server immer alle Clients ansprechen kannst. Die Client-Klasse selber müsste nun beispielsweise auch eine send() methode besitzen.
 

JUserToto

Aktives Mitglied
Hallo nochmal,

ich glaube ich verstehe in welche Richtung das geht. Einen groben Denkfehler habe ich nun schon erkannt. (Ich dachte die Accept Methode reagiert auf eingehen Daten und nicht auf eingehende Verbindungen)
Ich erzeuge also bei jedem erfolgreichen Verbindungsversuch einen neuen Client als Thread...
Ich sammle die Clients im Server.

Mir ist aber nicht ganz klar was der Client tut. Er muss ja trotzdessen an die aktuellen Spieldaten kommen und die sind ja nicht "einfach da", er muss sie irgendwie vom Server anfragen... mir ist nicht klar wie ich da an einer "alle paar Sekunden fragen" Struktur wegkomme...

lg Toto
 

Bizarrus

Bekanntes Mitglied
Ich dachte die Accept Methode reagiert auf eingehen Daten und nicht auf eingehende Verbindungen
[...]
Ich erzeuge also bei jedem erfolgreichen Verbindungsversuch einen neuen Client als Thread...
Genau, die accept aggiert ausschließlich auf einem connect und blockt dann den Prozess. Deswegen muss zwangsläufig die "gerade verbundene Socket" in einem Thread untergebracht werden, damit weitere connections von anderen Clienten angenommen werden kann.

Ich sammle die Clients im Server.
Genau, wäre empfehlenswert, da du ja irgendwie die Clienten im nachhinein "bedienen" möchtest.

Er muss ja trotzdessen an die aktuellen Spieldaten kommen und die sind ja nicht "einfach da", er muss sie irgendwie vom Server anfragen...
Jein. Der Client empfängt. Sobald neue "Daten" verfügbar sind, musst du dem Clienten dies nur mitteilen.

Pass auf, kleines Beispiel an einem "Spiel" - Beispielsweise bei einem Schach-Spiel.
Zwei Clienten connecten zum Server und werden zusammen (da das Spiel mit Zweispieler noch nicht "voll" ist) in einer "AktuellesSpiel" Klasse gesetzt (Jedes Spiel, was gerade läuft besitzt eine Instanz und wird im Server in einer HashMap gestored). Beide Clienten melden sich bei einem laufendem Spiel (noch nicht vollem Spiel) an und bei diesem vorgang teilt der Server die aktuellen Spielstände mit (Beispielsweise Positionen der einzelnen Püppchen).

Wenn nun Client A eine Figur "bewegt", teilt dieser das dem Server mit, so nach dem Motto "Puppe 7 auf X,Y". Der Server reagiert darauf und speichert die neue Position in der Klasse "AktuellesSpiel" und teilt danach dem anderen Clienten die veränderung mit.

Hierbei müsstest du nun dir eine Art Kommunikations-Protokoll erarbeiten. Denn beide Seiten müssen in irgendeiner Form ja wissen, was die andere Seite senden kann.

In dem Falle könnntest du verschiedene Methoden nutzen um dies zu Visualisieren. entweder du nimmst beispielsweise XML oder du erarbeitest dir eine einfache Textbasierte Kommunikation mit irgendwelchen Trennzeichen:

[XML]
<spieler>
<action>Wechsle Position</action>
<wasdenn>Eine Puppe</wasdenn>
<position>
<von_x>0</von_x>
<von_y>0</von_y>
<nach_x>1</nach_x>
<nach_y>1</nach_y>
</position>
</spieler>
[/XML]

Java:
// AKTION:VON_X:VON_Y:ZU_X:ZUY;
change_position:0:0:1:1

Dies wäre einmal ein grobes Beispiel, wie du derartiges Visualisieren könntest..
 

JUserToto

Aktives Mitglied
Hallo,

vielen, vielen Dank für die ausführliche Erklärung. Ich denke ich habe es nun verstanden und schaue mal, wie ich zurecht komme. :)
lg Toto
 

JUserToto

Aktives Mitglied
Hallo nochmal,

ich dachte eigentlich meine Fragen hätten sich erledigt. Da es aber nach wie vor nicht so funktioniert, wie ich es gerne hätte frag ich besser nochmal nach.

Ich habe nun den Server entsprechend umgeschrieben.

Java:
public Server()  {
            /* Sammlung der verbundenen Sockets. */
            sockets = new HashMap();

            /* Server erstellt ein neues Spiel */
            spiel = new Spiel();

            /* Erstellen des Serversockets. */
            server = new ServerSocket(57070);

            /* Thread der auf Verbindung zu Clients wartet. */
            new Thread(new ClientListener()).start();
}

Der Server startet also einen Thread, der auf neue Clienten wartet. Die run Methode sieht folgendermaßen aus:

Java:
@Override
        public void run() {
            while (true) {
                    /* Server nimmt neue Clienten an... */
                    Socket socket = server.accept();
                    
                    /* Client wird erzeugt und gestartet. */
                    Client con = new Client(socket,
                            socket.getInetAddress().getHostName(), spiel);
                    new Thread(con).start();
                    
                    /* Socket wird der Socketsammlung hinzugefuegt. */
                    sockets.put(socket.getInetAddress().getHostName(), socket);
            }
        }

Hier ist mir schon nicht ganz klar: Wieso startet der Server den Thread des Clienten? Zum Clienten gehört eine GUI, müsste diese nicht mit diesem Code immer auf dem Server-System erstellt werden? Würde ich den Thread aus dem Menü heraus starten lassen, würde mir jedoch der Socket des Clienten fehlen... Da drehe ich mich gedanklich im Kreis.

Der eigentliche Fehler der nun auftritt ist aber Folgender... Im Konstruktor des Clients versuche ich, mir die Streams geben zu lassen.

Java:
public Client(Socket socket, String spieler, Spiel spiel) {
        this.serverSocket = socket;
        out =  new ObjectOutputStream(serverSocket.getOutputStream());
        in =  new ObjectInputStream(serverSocket.getInputStream());
...
}

Hier stürzt das Programm ab mit dem Fehler: "java.net.SocketException: Software caused connection abort: recv failed" :(


lg Toto
 

Stroker89

Bekanntes Mitglied
in und out gehören in einen try catch Block.

Java:
try {
    in = new ObjectInputStream(socket.getInputStream());
    out = new ObjectOutputStream(socket.getOutputStream());
} catch (StreamCorruptedException e1) {
    e1.printStackTrace();
} catch (IOException e1) {
    e1.printStackTrace();
}

Kannst mal den code Zeigen wie du Daten empfängst und wie du zu dem Server connectest? Sind Server und Client in einem Programm oder was?

Gruß
 
B

Bizzi

Gast
Ich bins, Bizarrus.
Du hast die accept methode immer noch im server.
ich schick gleich mal einen teil meiner server/client architektur.

Entferne den Thread im Server, packe alles vom serverthread dort rein, und erstelle ein Thread bei accept!
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
T TCP mit und ohne Threads Netzwerkprogrammierung 1
Yonnig Threads mit Client/Server und GUI (laufend bis button-click) Netzwerkprogrammierung 9
K Threads/Server/telnet Fehler Netzwerkprogrammierung 2
D Exception Handling bei In/Outputsockets in eigenen Threads Netzwerkprogrammierung 1
C Frage zu Threads & Server Netzwerkprogrammierung 4
K Threads closen und Sockets schliessen Netzwerkprogrammierung 5
P RMI Threads die über RMI auf Datenbank zugreifen Netzwerkprogrammierung 2
S HTTP ServerSockets und Threads Netzwerkprogrammierung 5
B Sockets, Threads & Plugins Netzwerkprogrammierung 7
T Verbindungsversuche über TCP Sockets von mehreren Threads führt zu Serverabsturz Netzwerkprogrammierung 2
R Threads mit einem WebService Netzwerkprogrammierung 4
M Verständnisfrage zu RMI und Threads Netzwerkprogrammierung 2
L einfacher server ohne threads Netzwerkprogrammierung 4
A Threads auflisten und nacheinander ansprechen Netzwerkprogrammierung 6
C I/O - Synchronisation durch Threads in einem ChatClient Netzwerkprogrammierung 4
J Probleme mit Threads (Client terminiert) Netzwerkprogrammierung 4
P Threads einbinden Netzwerkprogrammierung 11
P RMI Callback (mit Threads?) Netzwerkprogrammierung 3
T RMI Threads und Synchronized Netzwerkprogrammierung 13
A Datenverteilung: Mehrere Threads verwenden? Netzwerkprogrammierung 4
S Threads beim Server koordinieren Netzwerkprogrammierung 5
L ClientServer mit 2 Threads Netzwerkprogrammierung 5
N Threads und Socketprogrammierung Netzwerkprogrammierung 4
G 1 Socket 2 Threads problem Netzwerkprogrammierung 13
K Problem mit Threads Netzwerkprogrammierung 3
S Threads bei Web Service sinnvoll oder Alternative? Netzwerkprogrammierung 2
K Hintergrund - Threads Netzwerkprogrammierung 3
G Socket Programmierung - Max. Threads Netzwerkprogrammierung 5
C NetScanner arbeitet trotz Threads langsam Netzwerkprogrammierung 6
L UDP-Server mit Threads Netzwerkprogrammierung 8
K Windows 10 Threads gleichzeitig Netzwerkprogrammierung 18
C Join von Threads bei I/O-Operation Netzwerkprogrammierung 6
F Threads synchronisieren mit Pipes Netzwerkprogrammierung 3
G benötige Beispiel für parallel ablaufende Threads Netzwerkprogrammierung 3
F Problem mit Threads und Sockets Netzwerkprogrammierung 3
TRunKX Threads beenden sich selber? Netzwerkprogrammierung 6
T Kleiner Chatserver: Threads oder Multiplex? Netzwerkprogrammierung 18
M Verständnisfrage zu den Streams Netzwerkprogrammierung 7
N Paket-Analysieren Byte-Streams Netzwerkprogrammierung 12
C Socket Cipher Streams Netzwerkprogrammierung 6
E Verfügbarkeit von Daten in Streams Netzwerkprogrammierung 4
V HTTP Streams setzen Netzwerkprogrammierung 10
N Socket Fehler bei Streams Netzwerkprogrammierung 2
1 SSH-Kommunikation - Ende eines Streams nicht erkenntlich Netzwerkprogrammierung 2
D Socket Streams schliessen .. Exception gewollt? Netzwerkprogrammierung 4
B Server mit meheren Streams/Aufgaben? Netzwerkprogrammierung 9
H RMI RPC "not suitable for streams and.." Netzwerkprogrammierung 2
T HTTP Encoding von Http-Streams Netzwerkprogrammierung 2
L mehrere Streams über einen Socket? Netzwerkprogrammierung 8
V Mehrere Streams durch einen Stream senden Netzwerkprogrammierung 14
M Streams verwenden Netzwerkprogrammierung 3
A Streams per RMI übergeben Netzwerkprogrammierung 6
P problem beim schließen eines Streams Netzwerkprogrammierung 6
K Selbe Streams mehrfach nutzen (zusätl. Thread) Netzwerkprogrammierung 6
J while-Schleife / Abbruchbed. beim Einlesen eines Streams Netzwerkprogrammierung 4
J Länge eines Streams Netzwerkprogrammierung 4
M Streams Bündeln Netzwerkprogrammierung 10
P Probleme mit Input- / Output-Streams Netzwerkprogrammierung 2
M Ende des Streams ohne Schließen/Checksumme mitsenden Netzwerkprogrammierung 2
M Probleme beim Abfangen von Streams Netzwerkprogrammierung 5
8 Socket Streams nur mit Byte? Netzwerkprogrammierung 2
E frage zu streams Netzwerkprogrammierung 2
F ResultSet in Streams Netzwerkprogrammierung 8
C IRC CHAT auslesen -> Sockets/input und output Streams Netzwerkprogrammierung 9

Ähnliche Java Themen

Neue Themen


Oben