Socket schließt bevor Daten komplett geladen

  • Themenstarter Themenstarter MiDniGG
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
M

MiDniGG

Gast
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:

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
 
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
 
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... 😉

Code:
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 🙂

Code:
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)
 
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.
Code:
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)
 
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.
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben