Socket: sporadisches Übertrag von Daten

Objektorientierte Programmiersprache auf Basis einer virtuellen Maschine (https://www.oracle.com/java/)
Antworten
Only86
Beiträge: 8
Registriert: Do Aug 11, 2011 2:41 pm

Socket: sporadisches Übertrag von Daten

Beitrag von Only86 » Mi Sep 21, 2011 2:46 pm

Hello World,

Ich habe eine Client-Server-Kommunikation auf meinem Mac entwicklet (testhalber), die im Moment nicht mehr machen soll, als byte[] auszutauschen. Der Client steht und macht dies eigentlich auch fleißg mit diesem Code:

Code: Alles auswählen

serverSocket = new Socket("localhost", 13000);
os = serverSocket.getOutputStream();
os.write(stream);
os.flush();
Aus Testzwecken lasse ich "stream" jedesmal ausgeben^^ Man weiss ja nie.
Jedenfalls empfange ich Serverseitig die Anfrage und übergebe sie an einen Thread, der diesen dann abhandelt.
Server:

Code: Alles auswählen

public class SocketServer {
	private static Thread t1;
	private static ServerSocket serverSocket;
	
	public static void main(String[] args) {
		
		try {
			serverSocket = new ServerSocket(13000);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		while(true){
			try{
			Socket clientSocket = serverSocket.accept();
			System.out.println("Request detected");
			t1 = new CommInterfaceServer(clientSocket);
			t1.run();
			}catch(Exception e){}
		}
	}
}
soweit läuft auch alles noch gut. Der Thread hat jetzt nur die Aufgabe die Daten zu empfangen (restliche FUnktionalität entfernt, weil.... so weit komme ich gar nicht).

Code: Alles auswählen

public class CommInterfaceServer extends Thread {

	private Socket clientSocket;
	private byte[] stream;

	public CommInterfaceServer(Socket clientSocket) {
		this.clientSocket = clientSocket;
	}

	public void run() {
		try {
			InputStream inPut = clientSocket.getInputStream();

			if (inPut.available() > 0) {
				stream = new byte[inPut.available()];
				inPut.read(stream);

				System.out.println("there is data -> size: " + stream.length);
			} else {
				System.out.println("no data, u mad?");
			}

			clientSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
Ich habe schon einige Test-Sockets geschrieben und die liefen immer problemlos. Dieses hat jedoch ein mir unverständliches Verhalten. Der request enthält nur sporadisch Daten obwohl immer gleich angefragt wird. Ich habe es mehrmals wiederholt und es scheint kein Muster dahinter zu stecken, wann Daten übertragen werden und wann nicht. Die Ausgabe sieht folgendermaßen aus:
Request detected
no data, u mad?
Request detected
no data, u mad?
Request detected
no data, u mad?
Request detected
there is data -> size: 44
Request detected
no data, u mad?
Request detected
no data, u mad?
Request detected
no data, u mad?
Request detected
no data, u mad?
Request detected
no data, u mad?
Request detected
no data, u mad?
Request detected
there is data -> size: 44
Request detected
no data, u mad?
Request detected
no data, u mad?
Request detected
no data, u mad?

Von all den Anfragen haben es nur zwei geschafft, die Daten korrekt zu übertragen. Woran kann das liegen? Ich dachte TCP-Sockets sind sehr übertragungssicher (anders als UDP). Kennt jemand das Problem oder hat meinen Schnipser schon entdeckt?
Ganz daneben kann der Code ja nicht sein, da immerhin ein paar durchkommen.

Vielen Dank schonmal für die Tipps!

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Socket: sporadisches Übertrag von Daten

Beitrag von Xin » Mi Sep 21, 2011 2:55 pm

Only86 hat geschrieben:

Code: Alles auswählen

		while(true){
			try{
			Socket clientSocket = serverSocket.accept();
			System.out.println("Request detected");
			t1 = new CommInterfaceServer(clientSocket);
			t1.run();
			}catch(Exception e){}
		}
Wenn man mal von "catch( Exception e ) {}" absieht, gefällt mir "while( true ) { serverSocket.accept(); }" überhaupt nicht.

Ich habe keine Ahnung, wie das in Java üblicherweise realisiert wird, aber mir fehlt das listen() hier. Durch kurzes Googlen fand ich ein Java-File, das ähnlich ohne listen() aufgebaut ist.

Ansonsten kann es sein, dass während t1.run() läuft, die Anfragen nicht beantwortet werden?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Socket: sporadisches Übertrag von Daten

Beitrag von nufan » Mi Sep 21, 2011 5:11 pm

Only86 hat geschrieben:

Code: Alles auswählen

t1.run();
Um in Java einen Thread zu benutzen, implementierst du die Methode run(), startest ihn jedoch über die Methode start(). In deinem Code ist das also ein ganz normaler Funktionsaufruf im Hauptthread deines Programms.
Only86 hat geschrieben:

Code: Alles auswählen

       public void run() {
          try {
             InputStream inPut = clientSocket.getInputStream();

             if (inPut.available() > 0) {
                stream = new byte[inPut.available()];
                inPut.read(stream);

                System.out.println("there is data -> size: " + stream.length);
             } else {
                System.out.println("no data, u mad?");
             }

             clientSocket.close();
          } catch (IOException e) {
             e.printStackTrace();
          }
       }
    }
Wenn ein Client verbindet fragst du sofort ab was er geschickt hat. Du kannst jedoch nicht sicher sein, ob der Client bereits mit der Übertragung fertig ist bzw. ob der Client überhaupt Daten schickt. Du musst also warten bis du Daten bekommst. Das kannst du über eine Schleife in deinem Thread lösen, den CPU solltest du über ein kurzes Thread.sleep() in den Schleifendurchgängen entlasten. Soweit ich weiß gibt es in Java keine Möglichkeit die Größe der empfangenen Daten (im voraus) abzufragen, also müsstest du zuerst die Größe der Daten übertragen und dann so lange lesen bis du diese Größe empfangen hast.
Xin hat geschrieben:Ich habe keine Ahnung, wie das in Java üblicherweise realisiert wird, aber mir fehlt das listen() hier.
accept() blockiert bis ein Client verbunden ist:

Code: Alles auswählen

Socket clientSocket = serverSocket.accept();

Only86
Beiträge: 8
Registriert: Do Aug 11, 2011 2:41 pm

Re: Socket: sporadisches Übertrag von Daten

Beitrag von Only86 » Do Sep 22, 2011 8:39 am

Danke nufan,

das warten hats gebracht. Das kann man aber anscheinend nur machen bevor man sich vom clientSocket den Inputstream holt, da dann schon alles erledigt ist und keine weiteren Daten im Inputstream landen. Das heisst dann aber auch, dass man nicht auf die available() zugreifen kann und so herausfinden kann, ob alle Daten angekommen sind. Ich habe jetzt einen 50 ms Sleep eingebaut und selbst mit einem byte[1000] ist das kein Problem.

Also vielen Dank! Ich werde nochmal testen, ab wann ich mit 50 ms Probleme kriege, aber generell, war es das ;-)
edit: sleep(10) reicht mindestens für byte[11000]. Ich werd da nochmal ein paar Tests durchführen von Android zu mac über wlan, wie es da steht.

CHEERS

P.S.: run() auf start() geändert.... just in case

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Socket: sporadisches Übertrag von Daten

Beitrag von nufan » Do Sep 22, 2011 8:50 am

Du solltest auf keinen Fall irgendwelche Annahmen an die Übertragungsgeschwindigkeit stellen. Am besten sendest du zuerst einen Integer (4 Byte) mit der Größe der aktuellen Übertragung in Byte und wartest dann so lange, bis available() die richtige Größe zurück gibt.

Antworten