# TCP Verbindung (Java Client und Visual Basic Server)



## Daniel_Schepers (9. Jul 2012)

Tach zusammen,

Ich bin mittlerweile einige zeitlang mit diesem Problem beschäftigt:
Ich will eine Server-Client TCP-Verbindung herstellen. Vorher habe ich beide als VB-Variante gebastelt, lief auch alles Super.
Jetzt will ich mit einem Android-Gerät via Java einen TCP-Client mit meinem Server verbinden lassen.
Das Problem ist folgendes:

Ich starte den Server
Dieser ist empfangsbereit und wartet auf Clientverbindung
Der Client verbindet sich mit dem Server
Der Client schickt im eine Nachricht ("200")
Der Server empfängt sofort die Nachricht ("200")
Der Server sendet Antwort ("300")
Es dauert jetzt 10 Sekunden
Der Client empfängt Nachricht ("300") und Verbindung wird abgebrochen.

Die Verbindung wird bei mir automatisch nach 10 Sekunden unterbrochen,
also empfängt der Client die Nachricht erst beim Abbruch. 

Warum dauert es solange zum zurücksenden? Ich habe den gleichen Server auch für meinen TCP Client für Visual Basic programmiert und dort sind keine Probleme. Was mache ich falsch?
Ich lese ja "zeilenweise". Kann das sein, dass ich da irgendwo etwas vergessen habe? Zeilenabschluss beim Server? Dort schreib ich ja nicht zeilenweise. 

Hier mal der Code (ein wenig vereinfacht)

*Der Servercode, läuft unter Windows 2003 Server*

        Dim listener As New TcpListener(50000)
        listener.Start()
        While True
            If listener.Pending Then
                Dim client As TcpClient = listener.AcceptTcpClient
                Dim stream As NetworkStream = client.GetStream
                Dim responsestring As String
                Dim clientdata As String
                Dim sendbytes As [Byte]()
                While True
                    Try
                        If stream.DataAvailable Then
                            Dim bytes(client.ReceiveBufferSize) As Byte
                            stream.Read(bytes, 0, CInt(client.ReceiveBufferSize))
                            clientdata = Encoding.ASCII.GetString(bytes)                        
                            responsestring = "300$"
                            sendbytes = Encoding.ASCII.GetBytes(responsestring)
                            stream.Write(sendbytes, 0, sendbytes.Length)
                         End If
                      Threading.Thread.Sleep(25)
                    Catch ex As Exception
                        fehler = ex.Message
                        Exit While
                    End Try
                End While
                client.Close()
            End If
            Threading.Thread.Sleep(25)
        End While


Hier der Java Code:


```
try {
	    clientSocket = new Socket(SERVER, 50000);
	    DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
	    BufferedReader inFromServer = new BufferedReader(new              
                                                                  InputStreamReader(clientSocket.getInputStream()));
	
            while (true) 
		 {
		    Send = "200";
			     
		     outToServer.writeBytes(Send);
			     
		     while (!inFromServer.ready()) {}
		     Return = inFromServer.readLine();
			    
		    }		  	 	  
     } catch (UnknownHostException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }
```

Joa, freu mich von euch zu hören


----------



## Poltergeist (9. Jul 2012)

ich wuerde so programmieren

```
public class Client extends thread {
...
public void run() {
      try {
           send = "200";
           StringBuffer buf = new StringBuffer();
           Socket client = new Socket(SERVER, 50000);
           InputStream in = client.getInputStream();
           OutputStream out = client.getOutputStream();
           out.write(send);
           while ((int b = in.read()) != -1) buf.append((char)b);
           in.close();
           out.close();
           client.close();
           return buf.toString();
      } catch (Exception e) {
           e.printStackTrace();
      }
      return null;
}
```
Sorry for my German.


----------



## NewLine (9. Jul 2012)

Kann schon sein das es daran liegt das du Zeilenweise lesen willst aber nicht Zeileweise schreibst.
Versuche im Server mal folgendes :

"300\n$"

(oder wie auch immer man Escape-Sequenzen in VB schreibt)
Dadurch sendest du einen expliziten Zeilenumbruch mit.
Gibt es denn in VB nicht die möglichkeit auch Zeilenweise zu schreiben ? (Wobei Windows eh \r\n schicken würde.)


----------



## Daniel_Schepers (9. Jul 2012)

Danke für eure Antworten.

Ich habe auf der Serverseite mal einfach etwas hinzugefügt und auf der Clientseite die 
andere Variante genommen:


sendbytes = Encoding.ASCII.GetBytes(responsestring + "\n$")
Stream.Write(sendbytes,0,sendbytes.length)


```
int b;
			     while (( b = inFromServer.read()) != -1) buf.append((char)b);
```


Habe es ebenfalls auch mit \n ausprobiert. Leider erhalte ich auf Clientseite dann einfach den Text mit "\n" am Ende. Oder müsste ich das mit ASCII am Ende hinzufügen? Nur da ich Erst seitdem ich Java
nutze auch Probleme habe, wollte ich mal hier bleiben.


----------



## NewLine (9. Jul 2012)

Es ging darum das du die Esacpe-Sequenz "\n" sendest. Oder binär : 0x0A. Und nicht den Text-String "\n".


----------



## Daniel_Schepers (9. Jul 2012)

Achso, jo Danke, allerdings bin ich dann jetzt überfragt wie es geht. 
Gehört zwar nicht hier ins Forum dann, aber, wie mache ich das?
Kannst du mir da weiterhelfen?


----------



## NewLine (9. Jul 2012)

Ich zitiere mich mal selbst :

"(oder wie auch immer man Escape-Sequenzen in VB schreibt)"

Da ich kein VB kann weis ich auch nicht wie man dort Escape-Sequenzen schreibt. In Java schreibt man einfach \n , \r , \t , usw ... oder wenn man aus der ASCII-Tabelle den Byte-Wert kennt einfach 0x0A , 0x0D , usw ... Eigentlich gehören Escape-Sequenzen zu den wichtigen Grundlagen.
Was auch sein könnte ist das \0 oder 0x00 am Ende fehlt ... bin der Meinung mal sowas gelesen zu haben das C *und Java ist ja in C/C++ geschrieben , also die VM* halt \0 am String-Ende erwartet ...

Allgemein wäre es wirklich einfacher wenn du mal rausbekommen könntest ob und wie man in VB halt Zeichenweise senden *also das gegenstück zu Java : PrintStream.println(String)*.


----------



## Daniel_Schepers (11. Jul 2012)

Morgen zusammen 

Vielen Dank für Eure Hilfe, jetzt hab ich eine Lösung die funktioniert.

Mein Server sendet scheinbar nach jedem Senden ein Abschlussbyte (Als Integer = 16).

Dann lese ich bei meinem Client die Schnittstelle solange aus, bis eben dieses Byte gelesen wird,
etwa so wie folgt:


```
int Readint = 0;
String Readletter = "";
String Readline = "";
StringBuffer buf = new StringBuffer();
while (Readint != 16)
{	
     Readint = inFromServer.read();
     if (Readint !=16)
        {
        buf.append((char)Readint);
        Readletter = buf.toString();
        Readline = Readline + Readletter;
        buf.delete(0, buf.length());
        }
 }
```


----------



## NewLine (11. Jul 2012)

Dir ist schon bewusst das ASCII 16 = 0x0A = "\n" ist oder ? Und das sollte BufferedReader.readLine() eigentlich auch als solches erkennen und damit erwartungsgemäß arbeiten. Warum es da aber Probleme gibt weis ich nicht da ich wie gesagt kein "VB" spreche.


----------



## r.w. (19. Jul 2012)

NewLine hat gesagt.:


> Dir ist schon bewusst das ASCII 16 = 0x0A = "\n" ist oder ? Und das sollte BufferedReader.readLine() eigentlich auch als solches erkennen und damit erwartungsgemäß arbeiten. Warum es da aber Probleme gibt weis ich nicht da ich wie gesagt kein "VB" spreche.



Falsch! ASCII (dezimal) 16 entspricht 0x10 und ist zwar auch ein Steuerzeichen, hat jedoch nichts mit einem Zeilenende zu tun.


@Daniel_Schepers:
In VB gibt es die Konstanten *vbLF* (0x0A) und *vbCRLF* (0x0D0A), 
die man an eine Zeichenkette hängen kann, um einen LineFeed, bzw. einen 
Return-LineFeed zu markieren. Wobei ich in Deinem Fall zu letzterem tendieren 
würde (also vbCRLF). 


Dein Basic-Code könnte dann eventuell so funktionieren:


```
sendbytes = Encoding.ASCII.GetBytes(responsestring + vbCRLF)
Stream.Write(sendbytes,0,sendbytes.length)
```

Ich hoffe, dass hilft Dir weiter, auch wenn schon ein paar Tage vergangen sind.

Gruß,
ROlf


----------



## NewLine (20. Jul 2012)

r.w. hat gesagt.:


> Falsch! ASCII (dezimal) 16 entspricht 0x10 und ist zwar auch ein Steuerzeichen, hat jedoch nichts mit einem Zeilenende zu tun.



Whoops ... kann ja mal vorkommen. Aber worauf ich hinaus wollte ist trotzdem klar geworden.


----------



## tuxedo (20. Jul 2012)

Tipp so nebenbei: Bei kurzen Nachrichten am Ende der Nachricht den Stream flushen... sonst kann es sein dass er die Nachricht nicht gleich sendet, sondern erstmal puffert und auf mehr Daten zu senden wartet.

Daneben gibt's noch den Nagle-Algorithmus. Den sollte man, wenn man nur wenige, aber kleine Datenhäppchen schickt die schnell ankommen sollen am besten abschalten. Wieso und warum: Wikipedia erklärt's dir. 

- Alex


----------



## Daniel_Schepers (22. Jan 2013)

Entschuldigt, dass ich mich so lang nicht meldete... Die Lösung bei VB die Konstante vbCrLf anzuhängen war genau das, was ich suchte. Vielen, vielen Dank an Alle!


----------

