Socket Datenübertragung schlägt nach dem zweite .read() fehl

  • Antworten:10
Hannes Bauer
  • Forum-Beiträge: 6

09.01.2014, 09:32:00 via Website

Hallo,

ich habe eine kleine Android App, die sich mit einem Server (Java Desktop Programm, welches als Socket Server fungiert) erstellt. Ich kann die Verbindung herstellen, das klappt alles wunderbar. Ich kann einen Befehl (JSONString) via Socket zum Server senden, kein Problem. Dieser Server schickt darauf hin auch einen JSON-String. Dieser kommt auch prinzipiell an, da dieser Datensatz aber größer als mein char[] Buffer ist, möchte ich mittels while() Schleife die Daten iterieren, aber beim zweiten Aufruf der .read() Methode des InputStreams wird aus Routine/Thread gesprungen. Dieses habe ich mittels Debugger gesehen, das Problem, es wird auch keine Exception geworfen. Diese ganze Prozedur habe ich natürlich in einen Thread() ausgelagert, also nicht direkt in der MainLoop.

1// DEFAULT IP
2 public static String SERVERIP = "192.168.1.100";
3
4 // DESIGNATE A PORT
5 public static final int SERVERPORT = 57311;
6
7
8 private Thread thread;
9 private boolean threadRunning = true;
10 private int sendCmdValue = 0;
11
12 public MainActivity() {
13
14 thread = new Thread(new Runnable() {
15 @Override
16 public void run() {
17 Socket client = null;
18 PrintWriter out = null;
19 //BufferedReader in = null;
20 DataInputStream in = null;
21
22 try {
23 client = new Socket(SERVERIP, SERVERPORT);
24
25 }
26 catch (UnknownHostException e) {
27 Log.d("Fehler", "UnknownHostException");
28 }
29 catch (IOException e) {
30 Log.d("Fehler", "IOException");
31 }
32
33 if (client == null)
34 Log.d("Fehler", "Keine Verbindung.");
35 else {
36 Log.d("Ok", "Verbindung erfolgreich");
37
38 try {
39 JSONObject cmdObject = null;
40
41 out = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
42 //in = new BufferedReader(new InputStreamReader(client.getInputStream()));
43 in = new DataInputStream(client.getInputStream());
44
45 String cmd = new JSONObject()
46 .put("cmd", "init")
47 .toString();
48
49 out.println(cmd);
50 out.flush();
51
52 // scheduling the cmd's
53 while(threadRunning) {
54 System.out.println("running: "+client.getReceiveBufferSize());
55
56 String line = ""; //in.readLine();
57 byte[] buffer = new byte[4096];
58 int read = in.read(buffer);
59
60 while(read != -1) {
61
62 line += String.valueOf(buffer);
63
64 read = in.read(buffer); // <-- hier bricht die Routine ab, springt komplett raus und der Thread wird nicht mehr ausgeführt !!!!
65 }
66
67 if (!line.isEmpty()) {
68 Log.d("data",line);
69 }
70 }
71 }
72 catch (JSONException e) {
73 e.printStackTrace();
74 }
75 catch (IOException e) {
76 e.printStackTrace();
77 }
78 catch (Exception e) {
79 e.printStackTrace();
80 }
81
82 }
83 }
84 });
85 thread.start();
86 }

Da ein ähnlicher Code auf eine PC funktioniert, gehe davon aus, das ich was besonderes bei Android beachten muss. Hatte jemand vielleicht schon das gleiche oder ein ähnliches Problem?

Vielen Dank für Euro Antwort !

Antworten
Stehpan Graf
  • Forum-Beiträge: 26

09.01.2014, 09:45:18 via App

Ich denke es wird schon eine Exception geben. ersetzt mal e.printStackTrace durch Log.d .

Antworten
Hannes Bauer
  • Forum-Beiträge: 6

09.01.2014, 09:59:43 via Website

Hallo Stephan,

erstmal Danke für die schnelle Antwort. Ich habe Zeilen 73,76,79 wie du gesagte hast mit Log.d() ersetzt. Ich habe zusätzlich Breakpoints an diese Stellen gesetzt. Es wird nichts darüber ausgegeben und der Debugger springt nicht in diese Exceptions.

Antworten
Stehpan Graf
  • Forum-Beiträge: 26

09.01.2014, 10:07:43 via App

Der erste read Aufruf liefert aber einen String? Kommentier mal die Schleife aus und lass dir den mal ausgeben.

Antworten
Hannes Bauer
  • Forum-Beiträge: 6

09.01.2014, 10:28:13 via Website

[code]

D/data﹕ {
"cmd" : "init",
"data":
[
{
"Titel": "FunkID",
"Name": "ID",
"Data": {
"min": 1,
"Rows": [
{
...
[/code]

Ich bekomme den Anfang des JSON-Blocks, laut .read() sind 4076 Byte zurückgekommen (in int read) !?
Es fehlen halt noch ein paar Zeichen, die eigentlich ja noch kommen müssten.

Jetzt ist beim debuggen folgender Eintrag in Logcat gekommen:

101-09 04:25:38.049 383-565/system_process W/InputMethodManagerService﹕ Got RemoteException sending setActive(false) notification to pid 5085 uid 10052
201-09 04:25:38.069 513-3272/com.android.inputmethod.latin W/Binder﹕ Caught a RuntimeException from the binder stub implementation.
3 java.lang.NullPointerException
4 at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280)
5 at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129)
6 at android.os.Binder.execTransact(Binder.java:404)
7 at dalvik.system.NativeStart.run(Native Method)


Hat das was damit zu tun ?

Antworten
Stehpan Graf
  • Forum-Beiträge: 26

09.01.2014, 10:56:34 via App

Probier es mal mit einem read aufruf, der nur ein Zeichen liest (natürlich in Schleife).

Antworten
Hannes Bauer
  • Forum-Beiträge: 6

09.01.2014, 11:22:36 via Website

Jetzt habe ich mal Zeichenweise gelesen. Zusätzlich habe ich nur den Text "Test" von der Server Applikation ausgeben lassen. Der Effekt ist der gleiche. Es wird gelesen, bis anscheinend kein Zeichen mehr vorhanden ist !?!

1345-5360/de.frss.tellscale D/data﹕ t
201-09 05:15:06.019 5345-5360/de.frss.tellscale D/data﹕ e
301-09 05:15:06.029 5345-5360/de.frss.tellscale D/data﹕ s
401-09 05:15:06.029 5345-5360/de.frss.tellscale D/data﹕ t
501-09 05:15:06.029 5345-5360/de.frss.tellscale D/data﹕ [ 01-09 05:15:07.859 383: 574 W/InputMethodManagerService ]
6 Got RemoteException sending setActive(false) notification to pid 5298 uid 10052
701-09 05:15:07.879 513-525/com.android.inputmethod.latin W/Binder﹕ Caught a RuntimeException from the binder stub implementation.
8 java.lang.NullPointerException
9 at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280)
10 at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129)
11 at android.os.Binder.execTransact(Binder.java:404)
12 at dalvik.system.NativeStart.run(Native Method)


Ich habe das Gefühl, bis .read() nicht mehr in der Lage ist ein weiteres Zeichen zu hohlen, Abbruch ! Es muss ja auch was mit der Fehlermeldung zu tun haben.

1513-525/com.android.inputmethod.latin W/Binder﹕ Caught a RuntimeException from the binder stub implementation.

Weiss jemand, was diese zu bedeuten hat ?

Antworten
Hannes Bauer
  • Forum-Beiträge: 6

09.01.2014, 17:15:11 via Website

Nein, es war durch das viele Testen drin geblieben. Ich habe es wieder auf char[] gesetzt !

Ich habe das Problem gefunden. Ohne ein abschließendes "\n" wurden die letzten Daten nicht gesendet und wenn keine Daten kommen, blockiert .read().

Ich habe es durch folgendes Konstrukt gelöst:

1// liegt was in buffer ?
2 if (in.ready()) {
3
4 while(in.ready()) {
5 // alles auslesen
6 read = in.read(buffer);
7 ...
8 }
9 // Auswertung ...
10
11}
12else { // weiter im Thread
13}

Vielen Dank an alle Beteiligten.

— geändert am 09.01.2014, 17:22:19

Antworten
impjor
  • Forum-Beiträge: 1.793

09.01.2014, 17:19:07 via App

Warum benutzt du denn nicht den BufferedReader, sonden den DataInputStream, wenn du eh' nur bytes liest und zu strings umwandelst?
DataInputStream wird verwendet wenn man Text, Ints, Longs, usw. aus demselben Stream lesen möchte.

LG

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

Antworten
Hannes Bauer
  • Forum-Beiträge: 6

09.01.2014, 17:24:10 via Website

Siehe meinen vorherige Antwort, das kam durch das ganze Testen und Ausprobieren. Du hast natürlich recht mit der Benutzung. Ich benutze jetzt auch wieder BufferedReader. Danke für den Hinweis.

Antworten