# Socket schließt bevor Daten komplett geladen



## MiDniGG (1. Feb 2008)

Hi,

bin grad dabei meinen HFS ma etwas weiterzumachen. Dabei bin ich auf folgendes Problem gestoßen:

Erst mal geb ich auf ner HTML-Seite alle "freien" Daten an. Mit klick auf einen der Links kann man die Datei dann runterladen. Gelesen und Geschrieben wird alles über Input / OutputStreams. 
Das läuft alles ganz schön ohne Problem. Jedoch, wenn die Datei zu "groß" ist (also mit 500 KB kam der Fehler) wird der InputStream, sowie der Socket geschlossen, bevor die Datei fertig geladen ist. Somit muss man bei ner Datei von 500 KB ca 10 mal F5 drücken bis mal was passiert... Und das ist nicht toll ^^

Hier noch n bisschen Code:


```
new Thread(new Runnable()
		{
			public void run()
			{
				try
				{
					dsl = new DataSourceList();
					dsl.load(new File("C:/properties.prop"));
					ss = new ServerSocket(port);
					while(true)
					{
						try
						{
							final Socket so = ss.accept();
	
							new Thread(new Runnable()
							{
								public void run()
								{
									try
									{
										byte[] bytes = null;
										String request = null;
										InputStream is = so.getInputStream();
										int ch = 0;
										StringBuffer buffy = new StringBuffer();
										while (buffy.length() < 3 || !buffy.substring(buffy.length() - 3, buffy.length()).trim().isEmpty())
										{
											ch = is.read();
											buffy.append((char)ch);
										}
										request = buffy.substring(buffy.indexOf("GET ") + 4, buffy.indexOf(" ", buffy.indexOf("GET ") + 4)).replaceAll("%20", " ");
										DataSource ds = dsl.getDataSourceByRequest(request);
										BufferedInputStream bis = new BufferedInputStream(new FileInputStream(ds.getFile()));
										bytes = new byte[(int)ds.getFile().length()];
										bis.read(bytes);
										answer(so, bytes, ds.getMime(), ds.getFile());
										bis.close();
					//					is.close();
					//					so.close();
									}
									catch(IOException ioe)
									{
										ioe.printStackTrace();
									}
								}
							}).start();
						}
						catch(FileNotFoundException fnfe)
						{
							fnfe.printStackTrace();
						}
						catch(SocketException se)
						{
							
						}
						catch(IOException ioe)
						{
							ioe.printStackTrace();
						}
					}
				}
				catch(FileNotFoundException fnfe)
				{
					fnfe.printStackTrace();
				}
				catch(IOException ioe)
				{
					ioe.printStackTrace();
				}
			}
		}).start();
```

So. Falls einer ne Idee hat. Nur raus damit. Falls ich irgendwelchen Blödsinn in der Erläuterung geschrieben hab. Sorry! Frag einfach nomma nach 

cya


----------



## MiDniGG (11. Sep 2008)

Ich sitz grad mal wieder vor diesem "Monster". Gibt es vllt. mittlerweise jemand der ne Idee hat an was das liegt?

Oder hat jemand ne andere Idee, wie ich das machen könnte? Ich hab schon über andere Streams nachgedacht. Aber ob das so hilfreich ist?!

Gruß Andy


----------



## MiDniGG (12. Sep 2008)

So. Habs etz mal soweit, dass es geht. Aber seeehr unschön, da er immer eine SocketException schmeißt...

Hab hier mal den Code, wenn es jmd. interessiert.

Hat vllt. jetzt noch jemand eine Idee, wie man das schöner bzw. erst mal ohne Exception machen kann? Ich mein die Ex. stört das Programm nicht. Alles läuft schön weiter. Aber muss ja nicht sein... 


```
public static void startServer(final int port) {
		new Thread(new Runnable(){
			public void run() {
				try {
					dsl = new DataSourceList();
					dsl.load(new File("C:\\properties.prop"));
					ss = new ServerSocket(port);
					while(true) {
						try {
							final Socket so = ss.accept();
							final InputStream is = so.getInputStream();
							new Thread(new Runnable(){
								DataOutputStream outStream = null;
								DataInputStream input = null;
								public void run() {
									try {
										byte[] bytes = null;
										String request = null;
										int ch = 0;
										StringBuffer buffy = new StringBuffer();
										while(buffy.length() < 3 || !buffy.substring(buffy.length() - 3, buffy.length()).trim().isEmpty()) {
											ch = is.read();
											buffy.append((char)ch);
										}
										String file = buffy.substring(buffy.indexOf("GET ") + 4, buffy.indexOf(" HTTP/"));
										if(file.contains("%20")) {
											file = file.replaceAll("%20", " ");
										}
										String mime = null;
										if(file.length() > 1) {
											FileReader fr = new FileReader("C:\\properties.prop");
											BufferedReader read = new BufferedReader(fr);
											String filename = null;
											boolean eof = false;
											while(!eof) {
												String line = read.readLine();
												if(line != null) {
													if(line.contains(file)) {
														filename = line.substring(0, line.indexOf("*"));
														mime = line.substring(line.lastIndexOf("*") + 1, line.length());
													}
												}
												else {
													eof = true;
												}
											}
											File dlFile = new File(filename);
							                outStream = new DataOutputStream(new BufferedOutputStream(so.getOutputStream()));
							                input = new DataInputStream(new BufferedInputStream(new FileInputStream(dlFile)));
							                
							                byte[] b = new byte[(int)dlFile.length()];
							                StringBuilder sb = new StringBuilder();
							                outStream.write(("HTTP/1.1 200 OK\n").getBytes());
							                outStream.write(("Server: File-Server by Anprie\n").getBytes());
							                outStream.write(("Content-Length: " + b.length + "\n").getBytes());
							                outStream.write(("Content-Language: de\n").getBytes());
							                outStream.write(("Content-Type: " + mime + "\n").getBytes());
							                outStream.write(("Connection: close\n\n").getBytes());
							                input.read(b);
							                if(mime.equals("text/txt")) {
								                for(int i = 0; i < b.length; i++) {
								                	sb.append((char)b[i]);
								                }
							                }
							                //so funktioniert es. Aber nur mit SocketException
							                while(!so.isClosed()) {
								                outStream.write(b);
							                }
										}
										else {
											request = buffy.substring(buffy.indexOf("GET ") + 4, buffy.indexOf(" ", buffy.indexOf("GET ") + 4)).replaceAll("%20", " ");
											DataSource ds = dsl.getDataSourceByRequest(request);
											BufferedInputStream bis = new BufferedInputStream(new FileInputStream(ds.getFile()));
											bytes = new byte[(int)ds.getFile().length()];
											bis.read(bytes);
											answer(so, bytes, ds.getMime(), ds.getFile());
											bis.close();
										}
									}
									catch(SocketException se) {
										se.printStackTrace();
									}
									catch(IOException ioe) {
										ioe.printStackTrace();
									}
									finally{
						                if(outStream != null){try{outStream.close();}catch(IOException e){e.printStackTrace();}}
						                if(input != null){try{input.close();}catch(IOException e){e.printStackTrace();}}
						                try{so.close();}catch(IOException e){e.printStackTrace();}
						                try{is.close();}catch(IOException e){e.printStackTrace();}
									}
								}
							}).start();
						}
						catch(FileNotFoundException fnfe) {
							fnfe.printStackTrace();
						}
						catch(SocketException se) {}
						catch(IOException ioe) {
							ioe.printStackTrace();
						}
					}
				}
				catch(FileNotFoundException fnfe) {
					fnfe.printStackTrace();
				}
				catch(IOException ioe) {
					ioe.printStackTrace();
				}
			}
		}).start();
	}
```

Hier hab ich dann noch die Exception. Vielleicht fällt euch ja was ein 


```
java.net.SocketException: Connection reset by peer: socket write error
	at java.net.SocketOutputStream.socketWrite0(Native Method)
	at java.net.SocketOutputStream.socketWrite(Unknown Source)
	at java.net.SocketOutputStream.write(Unknown Source)
	at java.io.BufferedOutputStream.write(Unknown Source)
	at java.io.DataOutputStream.write(Unknown Source)
	at java.io.FilterOutputStream.write(Unknown Source)
	at de.anprie.model.StartServer$1$1.run(StartServer.java:89)
	at java.lang.Thread.run(Unknown Source)
```


----------



## kleiner_held (12. Sep 2008)

I. Zum konkreten Problem
Dein Lesen und Schreiben der Daten (Zeile 52 - 69) ist nicht gut geloest
Du nutzt DataInputStream und DataOutputStream um Binaerdaten zu lesen und zu schreiben -> unnoetig. 
Du legst einen (eventuell riesigen) byte[] buffer an, testest aber nicht ob er beim Lesen wirklich gefuellt wird and dann schreibst du ihn in einer while Schleife mehrmals?!
Folgendes Beispiel ist eine typische Implementierung um Daten von einem InputStream in einen OutputStream zu kopieren, mit Java NIO wuerde es noch schneller gehen.

```
BufferedOutputStream outStream = new BufferedOutputStream(so.getOutputStream());
BufferedInputStream inStream = new BufferedInputStream(new FileInputStream(dlFile));
// Hier deinen Code zum Schreiben des  HTTP Response Header einfuegen
byte[] b = new byte[10000]; // ca 10 KB Buffer
int readLength;
while ((readLength = inStream.read(b)) != -1)
{
   outStream.write(b, 0, readLength);
}
```

II. ein paar andere Hinweise
Das HTTP Protokoll so rudimentaer zu implementieren wie du es machst halte ich fuer keine gute Idee. 
Nimm entweder eine fertige HTTP Server Implementierung z.B.: Apache HTTPD oder einen Servlet Container wie Tomcat (benoetigt aber halt eine Einarbeitung in Servlets)


----------



## HoaX (12. Sep 2008)

jetty lässt sich sehr leicht in anwendungen integrieren und kann fast alles


----------



## MiDniGG (12. Sep 2008)

Hey

@kleiner_held: Danke mal für die Tipps. Diese Data-I/O-Streams hab ich nur ma so testweise genommen und vergessen wieder raus zu tun. Danke ans erinnern ;-)
Das mit dem Puffer ist auch gut zu wissen. Ich nehm dann wohl mal dein Beispiel.
Zu den Servern werd ich mich ma en bisschen durchlesen und es passenste nehmen.

Danke nochmal!

@HoaX: Was immer genau jetty ist. Ich schau es mir an 

Gruß Andy.


----------

