# Sockets: ein alter Hut - für Euch - für mich nicht!



## data89 (5. Sep 2008)

Hallo,

ich möchte mich in die Netzwetzwerkkommunikation mittels Sockets in Java einarbeiten. Grundlagen habe ich mir schon in diversen Tutorialen angeeignet.

Nun möchte ich zwei "Programme" habe: Client und Server. Beide sollen miteinander Kommunizieren können! Ein Beispiel für einen Server (mit Threads) habe ich hier im Forum gefunden!

Nun muss ich noch den Clienten hinbekommen! Dieser sollte auch in einem Thread laufen und Nachrichten entgegennehmen und versenden können (an den Server)!

Bis hier hin kein Problem. Ich habe auch schon einen einfachen Clienten geschrieben, der sich nach einer gesendeten Nachricht beendet (s.u.).
Doch nun hab ich keine Ahnung! Ich weiß nicht wie ich weitermachen soll ...

Könnt Ihr mir weiterhelfen?
data89

=====================================
Tserver:

```
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;


public class Tserver {

	public static void main(String[] args) {
		try {
			System.out.println( "[Server]~> Server gestartet!" );
			// Server aufbauen
			ServerSocket server = new ServerSocket(1234);
			Socket s;
			while(true) {
			// Auf verbindung warten
			s = server.accept();
			// kommunikation an einen nebenläufigen Thread abgeben
			ServerThread t = new ServerThread(s);
			t.start();
			// und wieder auf neue Verbindungen warten
			}
		} catch( IOException e ) {
			System.out.println( "[Server]~> " + e.toString() );
		}
	}
	
}
```

ServerThread: 

```
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;


public class ServerThread extends Thread {
private Socket s;
public ServerThread(Socket s) {
this.s = s;
}

public void run() {
try {
	// lesen
	BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
	String text = in.readLine();
	System.out.println( "[Server]~> " + text );
	// schreiben

	BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
	out.write(text.toUpperCase());
	out.newLine();
	out.flush();

	// aufräumen
	out.close();
	in.close();
} catch( IOException e ) {
	System.out.println( "[Server]~> " + e.toString() );
}
}
}
```

Client:

```
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;


public class Client {

	public Client( Socket socket ) throws IOException {
		PrintWriter pw = new PrintWriter( socket.getOutputStream() );
		pw.print( "Hallo Welt!" );
		pw.flush();
		socket.close();
	}
	
	public static void main(String[] args) {
		try {
			Socket ss = new Socket( "127.0.0.1" , 1234 );
			Client client = new Client( ss );
		} catch( IOException e ) {
			System.out.println( "[Client]~> " + e.toString() );
		}
	}
	
}
```


----------



## Murray (5. Sep 2008)

Was ist denn genau das Problem? Der Client muss, nachdem er seine Nachricht an der Server geschickt hat, die Antwort auslesen (-> Socket#getInputStream) . Und wenn es mehr als eine Nachricht gibt, dann sollte er den Socket nicht sofort wieder schliessen, sondern die Verbindung halten. Daher sollte weder das Senden der Nachricht, noch das Schliessen des Stream im Konstruktor erfolgen.


----------



## data89 (5. Sep 2008)

Also ich bekomme es nicht hin einen Client und einen dzugehörigen Thread zu schreiben, der die entsprechenden Methoden hat  :cry:


----------



## Murray (5. Sep 2008)

Was soll der Client genau machen, und wozu braucht er einen Thread?


----------



## data89 (6. Sep 2008)

Der Client soll Nachrichten annehmen und mit System.out... ausgeben und Nachrichten Senden können! Den Thread benutze ich, damit das Socket erhalten bleibt!


----------



## data89 (6. Sep 2008)

Ich habe mal am Client angefangen, doch wenn ich ihn gestartet habe kommt immer "Connection refused"!

Client:

```
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;


public class Client {

	private ClientThread t;
	
	
	public Client( ) {}
	
	public void MessageToServer( ) {
		t.SendMessage( "Nachricht vom Client an den Server!" );
	}
	
	public static void main(String[] args) {
		
		try {
			System.out.println( "[Client]~> Client gestartet!" );
			
			// Client aufbauen
			Socket socket = new Socket( "127.0.0.1" , 11111 );
			Client client = new Client( );
			
			while( true ) {
			
				// Kommunikation an thread abgeben
				ClientThread t = new ClientThread( socket );
				t.start();
				
			}
		} catch( IOException e ) {
			System.out.println( "[Client]~> " + e.toString() );
		}
		
	}
	
}
```

ClientThread:

```
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;


public class ClientThread extends Thread {

	private Socket s;
	
	public ClientThread( Socket socket ) {
		this.s = socket;
	}
	
	public void run() {
		
		try {

			BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
			String text = in.readLine();
			System.out.println( "[Client]~> " + text );
			
		} catch( IOException e ) {
			System.out.println( "[Client]~> " + e.toString() );
		}
		
	}
	
	public void SendMessage( String message ) {
		
	}
	
	
}
```

data89


----------



## DocRandom (7. Sep 2008)

Moin!

*Connection refused* bedeutet in Deinem Fall, das Du zum *falschen Port* verbindest.
Du startest den *Server auf Port 1234*, verbindest Dich aber mit dem *Clienten auf Port 11111*.
Das kann nicht funktionieren.

lg
DocRandom


----------



## Murray (8. Sep 2008)

data89 hat gesagt.:
			
		

> Der Client soll Nachrichten annehmen und mit System.out... ausgeben und Nachrichten Senden können! Den Thread benutze ich, damit das Socket erhalten bleibt!


Wozu man da zwingend einen Thread braucht, verstehe ich noch nicht. Auf jeden Fall ist das

```
while( true ) {
         
            // Kommunikation an thread abgeben
            ClientThread t = new ClientThread( socket );
            t.start();
            
         }
```
eher Unfug - es wird ohne Verzögerung ein Thread nach dem anderen erzeugt und gestartet. Und alle diese Threads lesen (blockierend) vom gleichen Stream, was sicher nicht gewollt ist - der Server schreibt auf den Stream die Daten doch sicher nur einmal pro Client. Und selbst wenn der Server genug Daten für alle Threads liefert, würde er das wohl nicht so schnell tun, wie der Client neue Threads erzeugen kann. Daher wird es früher oder später (eher früher) einen OutOfMemoryError geben.


----------



## data89 (8. Sep 2008)

Murray hat gesagt.:
			
		

> Wozu man da zwingend einen Thread braucht, verstehe ich noch nicht.



*Man benötigt garkeinen Thread, um die Verbindung offen zu halten?* Ja wenn das so ist! Ich hatte irgendwo gelesen, dass man einen Thread benötigt, um die Verbindung offen zu halten ...

Also mir geht es darum einfach zwei Klassen zu erstellen, mit denen ich eine Verbindung zwischen zwei Programmen realisieren kann - zunächst ein sehr trivialer Chat.

Gibt es irgendwo eine Seite wo ein ganz einfaches Beispiel gegeben wird (hab ich mit Google noch nicht gefunden)? Oder: Was muss ich zu diesem Beispiel (http://www.peuss.com/java/Sockets.php) noch hinzufügen, damit die Verbindung dauerhaft offen bleibt?

data89


----------



## Murray (8. Sep 2008)

Solange der Client den Socket nicht zumacht (Socket.close), bleibt die Verbindung auch bestehen. Der Client müsste nach meinem Verständnis in einer Endlosschleife Daten aus dem Stream lesen. Das bedingt erstmal noch keine Thread. Wenn man parallel aber auch Daten schicken will, dann braucht man einen (und nicht endlos viele) zusätzlichen Thread. 

Um im Hintergrund Daten von Server zu lesen, könnte die run-Methode des Thread etwa so aussehen:


```
public void run() {
  try {
    while ( true) {
      String data = socketReader.readLine(); //--- ein BufferedReader auf dem InputStream des Sockets
      processData( data); //--- was auch immer mit den Daten passieren soll
    }
  } catch ....
  }
}
```

Der Hauptthread der Anwendung kann derweil Daten (von der Konsole oder aus einer GUI) entgegennehmen und um Server schicken.


----------



## data89 (11. Sep 2008)

Danke für die Antwort!   
War genau das, was ich wissen wollte (der Rest hat sich erledigt!)!

data89  :idea:


----------

