# einfache TCP/IP Anwendung



## yofrly (23. Okt 2011)

Hallo Leute, 

Ich hab die Aufgabe bekommen einen bereits vorhandenen Workspace weiterzuprogrammieren. 
Es soll ein Echo-Server und ein passender Echo-Client auf Basis von TCP-Sockets
entwickelt werden, der alle Echo-Requests in einem einzigen Thread bearbeitet.
Für jeden Echo-Request baut ein Client eine TCP-Verbindung zum Server auf, sendet eine Echo-
PDU, wartet auf das Ergebnis und baut anschließend die Verbindung wieder ab.

Soweit bin ich bis jetzt: 

```
public class TCPSingleThreadedEchoClientThread extends AbstractClientThread
{	 
		private static Log log = LogFactory.getLog(TCPSingleThreadedEchoClientThread.class);
				
	    // Lokaler Port zur Kommunikation mit dem Echo-Server 
	    private int localPort;
	    		
	    // Name des Threads
	    private String threadName;
	    
	    // Nummer des Echo-Clients
	    private int numberOfClient;
	    
	    // Laenge einer Nachricht
	    private int messageLength;
	    
	    // Anzahl zu sendender Nachrichten je Thread
	    private int numberOfMessages;
	  
	    // Serverport 
	    private int serverPort;
	    
	    // Adresse des Servers
	    private String remoteServerAddress;
	    
	    // Denkzeit des Clients zwischen zwei Requests in ms
	    private int clientThinkTime;
	    
	    // Gemeinsame Daten der Threads
	    private SharedClientStatistics sharedData;
	    
	    // Socket-Verbindung
	    private Socket con;
	    private ObjectInputStream in;
	    private ObjectOutputStream out;
	  
	    // Zeitstempel für RTT-Berechnung und Kalender
		private long rttStartTime;
		private long rtt;
		
		@Override
		public void initialize(
			int serverPort,
			String remoteServerAddress,
			int numberOfClient, 
			int messageLength, 
			int numberOfMessages,
			int clientThinkTime,
			SharedClientStatistics sharedData)
		{		
		    this.serverPort = serverPort;
		    this.remoteServerAddress = remoteServerAddress;
		    this.numberOfClient = numberOfClient;
		    this.messageLength = messageLength;
		    this.numberOfMessages = numberOfMessages;
		    this.clientThinkTime = clientThinkTime;
		    this.sharedData = sharedData;
			this.setName("EchoClient-".concat(String.valueOf(numberOfClient+1)));    
			threadName = getName();
		}

		/**
		 * Run-Methode fuer den Test-Thread: 
		 * Client-Thread sendet hier alle Requests und wartet auf Antworten
		 */
		public void run() 
		{   
			sharedData.incrNumberOfLoggedInClients();
			  
	        /**
	         * Synchronisation mit allen anderen Client-Threads:
	         * Warten, bis alle Clients angemeldet sind und dann
	         * erst mit der Lasterzeugung beginnen
	         */
	        while (!sharedData.allClientsLoggedIn())
	       	{
	        	try {     
			        Thread.sleep(100);
	        	}
		        catch (InterruptedException e) {
		        	log.error("Sleep unterbrochen");
		        }
	        }
	        
	       
	        
	        /**
	         * Senden von Echo-Nachrichten
	         */
	        
	        for (int i = 0; i < numberOfMessages; i++) 
	        { 	
	        try {
	        	EchoPDU echo = new EchoPDU();
				
				con = new Socket(remoteServerAddress, serverPort);
				
				out = new ObjectOutputStream(con.getOutputStream());
				in = new ObjectInputStream(con.getInputStream());
	        	out.writeObject(echo);
	        	out.close();
				
				in.readObject();
				in.close();
				con.close();
				
					
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} 
				
	        }
			
		}	
 }
```


```
public class TCPSingleThreadedEchoServer
{	 
		private static Log log = LogFactory.getLog(TCPSingleThreadedEchoServer.class);

		private static int serverPort = 50000;
		
		// Verbindungstabelle: Hier werden alle aktiven Verbindungen zu Clients verwaltet
	    private static Map<String, Socket> connections = new ConcurrentHashMap<String, Socket>();
	 
	    // TCP-Socket des Servers (Listen-Socket)
	    private static ServerSocket serverSocket;
	    
	    // Laenge der Queue des Server-Sockets fuer ankommende Verbindungsaufbauwuensche
		private static final int backlog = 20;
		
		// Verbindungszaehler
		private static long nrConnections = 0;
		
		// Streams fuer TCP-Verbindung
		private static ObjectOutputStream out;
		private static ObjectInputStream in;
	
		/**
	     * Konstruktor
	     */
		public TCPSingleThreadedEchoServer()
		{		
		}
		
		/**
		 * main
		 * @param args
		 */

   	    public static void main (String args[])
   	    {
   	    	PropertyConfigurator.configureAndWatch("log4j.server.properties", 60 * 1000);
   	    	
   	    	// TODO: TCP-Serversocket registrieren
   	    	try {
				serverSocket = new ServerSocket(serverPort);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
   	    	
   	    	while (true) {
   	    		try {
   	    			// Auf ankommende Verbindungsaufbauwuensche warten
   	    			
   	    			Socket incomingConnectionFromClient = serverSocket.accept();
	            	   	    			
   	    			//TODO
   	    			
   	    			// Ein- und Ausgabe-Objektstrom erzeugen				
					out = new ObjectOutputStream(incomingConnectionFromClient.getOutputStream());
   	   				in = new ObjectInputStream(incomingConnectionFromClient.getInputStream());
   	    			
   	    			
   	   	   			//TODO: Neue Verbindung in Verbindungstabelle eintragen
   	   			    Object e = in.readObject();
	    			EchoPDU echo = (EchoPDU) e;
				    in.close();	

   	   	    		//TODO: Echo-Response senden
					out.writeObject(echo);
					out.close();
					serverSocket.close();
					
   	    		}
   	    		catch (Exception e) {
   	    			//TODO
   	    		}
   	   	    	
   	    	 }
   	    }
 }
```


```
public class EchoPDU implements Serializable
{	 
	private static final long serialVersionUID = -6172619032079227583L;
	
	String clientName; 		 // Name des Client-Threads, der den Request absendet
	String serverThreadName; // Name des Threads, der den Request im Server bearbeitet
	boolean lastRequest;	 // Kennzeichen, ob Client letzte Nachricht sendet. Dieses Kennzeichen
							 // dient dem Server dazu, um festzustellen, ob sich der Client nach der Nachricht beendet
	private long serverTime; // Zeit in Nanosekunden, die der Server benoetigt. Diese
							 // Zeit wird vom Server vor dem Absenden der Response eingetragen
	String message; 		 // Echo-Nachricht (eigentliche Nachricht in Textform)
  
	public EchoPDU()
	{
		clientName = null;
		serverThreadName = null;
		message = null;
		serverTime = 0;
		lastRequest = false;
	}
	
	public void setClientName(String name) 
	{
		this.clientName = name;
	}
	
	public void setServerThreadName(String name) 
	{
		this.serverThreadName = name;
	}
	
	public void setMessage(String msg) 
	{
		this.message= msg;
	}
	
	public void setServerTime(long time) 
	{
		this.serverTime = time;
	}
	
	public void setLastRequest (boolean last) 
	{
		this.lastRequest = last;
	}
	
	public String getClientName() 
	{
		return(clientName);
	}
	
	public String getServerThreadName() 
	{
		return(serverThreadName);
	}
	
	public String getMessage() 
	{
		return(message);
	}
	
	public long getServerTime() 
	{
		return(serverTime);
	}
	
	public boolean getLastRequest() 
	{
		return(lastRequest);
	}
}
```


```
public class BenchmarkingGuiSimulation implements BenchmarkingClientGuiInterface {
	
	private int timeCounter = 0;
	
	@Override
	public void showStartData(GuiStartData data) {
		
		System.out.println("Testbeginn: " + data.getStartTime());	
		System.out.println("Geplante Requests: " + data.getNumberOfRequests());
	}
	
	@Override
	public void showResultData(GuiResultData data) {
			
		System.out.println("Testende: " + data.getEndTime());
		System.out.println("Testdauer in s: " + data.getElapsedTime());	
		
		System.out.println("Gesendete Requests: " + data.getNumberOfSentRequests());
		System.out.println("Anzahl Responses: " + data.getNumberOfResponses());
		System.out.println("Anzahl verlorener Responses: " + data.getNumberOfLostResponses());
		
		System.out.println("Mittlere RTT in ms: " + data.getAvgRTT());
		System.out.println("Maximale RTT in ms: " + data.getMaxRTT());
		System.out.println("Minimale RTT in ms: " + data.getMinRTT());
		System.out.println("Mittlere Serverbearbeitungszeit in ms: " + data.getAvgServerTime());
		
		System.out.println("Maximale Heap-Belegung in MByte: " + data.getMaxHeapSize());
		System.out.println("Maximale CPU-Auslastung in %: " + data.getMaxCpuUsage());
	}
	
	@Override
	public void setMessageLine(String message) {
		System.out.println("*** Meldung: " + message+ " ***");
	}
	
	@Override
	public void addCurrentRunTime (long sec) {
		timeCounter += sec;
		System.out.println("Laufzeitzaehler: " + timeCounter);
	}
	
	@Override
	public void resetCurrentRunTime () {
		timeCounter = 0;
	}
	
	/**
	 * main
	 * @param args
	 */
	public static void main(String args[]) 
	{
		PropertyConfigurator.configureAndWatch("log4j.client.properties", 60 * 1000);
		new BenchmarkingGuiSimulation().doWork();
		
	}
	
	public void doWork()
	{
		// Input-parameter aus GUI
		GuiInputParameters parm = new GuiInputParameters();
		
		// GUI sammmelt Eingabedaten ...
		
		// Benchmarking-Client instanzieren und Benchmark starten
		
		BenchmarkingClient benchClient = new BenchmarkingClient();
		benchClient.executeTest(parm, this);
	}
}
```

Mir wird folgender Fehler angezeigt: 

```
at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(Unknown Source)
	at java.net.SocketInputStream.read(Unknown Source)
	at java.net.SocketInputStream.read(Unknown Source)
	at java.io.ObjectInputStream$PeekInputStream.peek(Unknown Source)
	at java.io.ObjectInputStream$BlockDataInputStream.peek(Unknown Source)
	at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
	at java.io.ObjectInputStream.readObject0(Unknown Source)
	at java.io.ObjectInputStream.readObject(Unknown Source)
	at edu.hm.dako.EchoApplication.TCPSingleThreaded.TCPSingleThreadedEchoClientThread.run(TCPSingleThreadedEchoClientThread.java:126)
java.net.SocketException: socket closed
```

Kann mir jemand sagen, was ich falsch gemacht habe?


----------



## turtle (23. Okt 2011)

Sorry, hab den Beitrag nicht bis zum Schluss gelesen, ignoriere diesen Post.


----------



## yofrly (23. Okt 2011)

Wieso? Im Grunde gehts nur um die Klassen Server und Client. Ich versteh nicht warum kein Datenaustausch stattfindet.  echo wird losgeschickt, angenommen vom Server, gecastet und dann wieder zurückgeschickt. Wo liegt der Fehler?


----------



## HoaX (23. Okt 2011)

Einfach lesen ... "java.net.SocketException: socket closed" an der Stelle java.net.SocketInputStream.socketRead0(Native Method). 
Du versuchst von einem geschlossenen Socket zu lesen. Und das liegt imo an Zeile 101 in einem Client.


----------



## TheRealSpikee (23. Okt 2011)

Client
Zeile 100

out.writeObject(Object);
out.close();
in.readObject();
in.close();

Das das kracht ist eigentlich jedem Java-Programmierer klar ...

richtig müsste es so lauten :


out.writeObject(Object);
in.readObject();
out.close();
in.close();

Du kannst nunmal nicht von einer geclosed Connection lesen ...


----------

