# unvollständige Daten: Http Client-Server-Kommunikation



## giofyxle (29. Aug 2006)

Ich schreibe gerade an einem Server (in java) der mit Clients (in C++) kommuniziert. Als Kommunikationsweg wurde das http-Protokoll festgelegt.

Der Server horcht in einer while Schleife auf Anfragen aus dem Netz. Wenn eine Anfrage ankommt, wird in dieser while-Schleife in einem neuen Thread eine Bearbeitungsklasse gestartet. In der Bearbeitungsklasse lese ich die Daten verarbeite sie zu einem Ergebnis (hier XML) und will diese zusammen mit einem http-Header an den Client zurückschicken.

Die Daten kommen aber nur dann zuverlässig beim Client an, wenn ich nach dem out.write();out.flush(); eine recht lange Zeit warte. Ich habe deshalb eine sleep-Funktion an dieser Stelle eingebaut.

Wenn ich diese Zeit zu kurz wähle, kommen beim Client nur Bruchstücke zufälliger Länge der zu übertragenden Daten an.


Ich kenne ein solches Problem aus einer reinen C++ Client-Server –Anwendung. Dort hatten wir allerdings kein http-Protokoll verwendet. Wir hatten damals vereinbart, dass der Empfänger immer ein Quittungsbyte an den Sender zurückschickt, wenn er die Daten vollständig erhalten hatte; der Sender musste dann solange warten.

Aber wie kann man das mit dem http_Protokoll machen?
Die sleep-Funktion ist ja nur eine dumme Krücke, die bestimmt nicht unter allen Voraussetzungen rausreicht….

Eine andere Lösung ist, das Socket nicht zu schliessen. Das habe ich auch ausprobiert. Aber was passiert, wenn der Server in den Bearbeitungsthreads das Socket nicht schliesst? Leidet darunter die Performance, oder werden die Ressourcen des Servers sinnlos verbraucht? Leider habe ich vom technischen Hintergrund zu wenig Vorstellung.



Hier mein Code:

zuerst die Serverschleife:

```
private void startServing()
{
while ( server != null  && shutdown.value == false)
	{
		Socket client = null;
		try
		{
			client = server.accept();
			Thread t = new  Thread( new Bearbeitung(client,this.config));
			t.start();
		}
		catch ( IOException e )
		{
			if ( client != null )
	    		try { client.close(); 
		}
		catch ( IOException e2 ) { e2.printStackTrace(); }
		client = null;		
	}  
}
```

Dann der Bearbeitungsthread:


```
public class Bearbeitung implements Runnable 
{
	private Socket client;
	private RkConfig config = null;

	public Bearbeitung(Socket s, RkConfig conf) 
{
		client = s;
		config = conf;
	}
	
	
	public void run() {
		if (client != null) {
			byte[] abErg = null;

			try {
				HttpInput input = new HttpInput(client.getInputStream());
				OutputStream out = client.getOutputStream();
	
				input.readHttp(); // 
				String strData = input.getDataString();
				strData = strData.trim();
				// jetzt Daten verarbeiten:
				abErg = datenVerarbeiten(strData);			
				
				
				// einen Http-Header als AsciiByte-Array erstellen:	
				HttpHeaders httphead = new HttpHeaders();
				httphead.setContentlength(abErg.length);

				byte[] abHead = httphead.writeHeaderToAsciiByteArray();
				// den Http-Header verschicken
				out.write(abHead);
				// Ergebnis verschicken.
				out.write(abErg);
				out.flush();
				

				// nur wenn ich hier lange warte, kommen beim Client die Daten 
				// zuverlässig an!
				Thread.sleep(50000);
				System.out.println("\r\nDaten an Client verschickt.");
			} 
			catch (IOException e) {e.printStackTrace();}
			catch (InterruptedException e) {e.printStackTrace();}
			finally 
			{
				try 
				{
					// genauso, wenn ich dieses Close wegnehme, funktioniert die
					// Datenübertragung...
					client.close();
				} 
				catch (IOException e) {e.printStackTrace();}
				client = null;
			}
		}
	}

}
```


Nochmals meine Fragen:


 - Verbrauche ich die Ressourcen des Servers, wenn serverseitig die Sockets nicht geschlossen werden?
- Gibt es eine andere Möglichkeit, festzustellen, wann der Client alle Daten empfangen hat, bzw. eine andere Möglichkeit, die Daten zu verschicken, so dass ich das Socket schliessen kann!?

Danke! Georg


----------



## mightymop (1. Sep 2006)

giofyxle hat gesagt.:
			
		

> Dann der Bearbeitungsthread:
> 
> 
> ```
> ...



Hallo Kollege...

also mir würde auf anhieb die erklärung einfallen, dass auf dem EthernetFrame für den Datenverand nur ca. 1500Bytes zur Verfügung stehen und da du dort alle Daten mit einem mal versuchst loszuschicken könnte es zu
einen Datenstau kommen... Versuch doch mal die Daten gestückelt in 1024 Bytes großen Paketen abzuschicken etwa so:


```
....
....

byte[] abHead = httphead.writeHeaderToAsciiByteArray();
// den Http-Header verschicken
int pos = 0;
while (pos<abHead.length){

      if (abHead.length>=1024) {
      out.write(abHead,pos,pos+1024); 
      out.flush();
      pos+=1024;
      }
      else {
      out.write(abHead,0,abHead.length); 
      out.flush();
        pos=abHead.length;
      }
}

// Ergebnis verschicken.
pos = 0;
while (pos<abErg.length){

      if (abErg.length>=1024) {
      out.write(abErg,pos,pos+1024); 
      out.flush();
      pos+=1024;
      }
      else {
      out.write(abHead,0,abErg.length); 
      out.flush();
        pos=abErg.length;
      }
}
....
....
```


der code ist mal eben auf die schnelle getippselt worden ... 
ich hoffe es klappt....

cu mightymop


----------



## giofyxle (1. Sep 2006)

Hallo!

Leider ist das nicht das Problem.
Egal, ob ich an die Write-Funktion den ganzen Puffer auf einmal übergebe, oder in 1024-er Stückchen, kommen die Daten beim Client manchmal unvollständig an.
Wie gesagt, wenn ich den Socket zum client nach dem write() nicht schliesse, oder vorher eine lange Zeit warte,  funktioniert alles wunderbar....


----------

