2015-04-20 3 views
7
Socket socket = new Socket("192.168.178.47", 82); 

OutputStream out = socket.getOutputStream(); 
out.write("{ \"phone\": \"23456789\" }".getBytes()); 
out.flush(); 

// ServerJava Output spült nur Daten auf einem engen

InputStream in = client.getInputStream(); 
ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 

int i = 0; 
while((i = in.read()) >= 0) { 
    bOut.write(i); 
} 

String complete = new String(bOut.toByteArray(), "UTF-8"); 

Ich hatte versucht, Daten über Output an eine Steckdose zu senden, aber die Daten Spülung nicht. Wenn ich am Ende ein out.close(); hinzufüge, dann funktioniert es einwandfrei, aber der Socket ist geschlossen und ich kann die Antwort nicht akzeptieren. Weiß jemand warum? Der Server gibt keine Art von Fehler. Ich hatte Java 1.7 benutzt!

+0

Wie sieht der Servercode aus? – Dan

+0

Wie haben Sie bestätigt, dass die Ausgabe nicht gesendet wurde? – Simon

+1

Nun, wissen Sie, ein 'OutputStream' hat' .flush() '. Außerdem ist die Art und Weise, wie Sie Ihre JSON schreiben, gebrochen: Sie verwendet die Standardcodierung der JRE. Warum verwenden Sie nicht stattdessen eine JSON-Bibliothek? – fge

Antwort

6

Es ist möglich, dass der Server für das Ende der Leitung wartet. Wenn dies der Fall ist „\ n“ auf den Text

+0

Das war genau das, was mein Programm tat. Danke für den Tipp! – gdawgrancid

1

Versuchen Sie es mit hinzufügen

socket.setTcpNoDelay(true); 

Es Pufferung ist, die aus Performance-Gründen (lesen Sie auf Nagle-Algorithmus) auftritt.

+0

Großartige Köpfe :) Ich habe versucht, vor Ihnen zu schreiben, aber diese Website begann wirklich langsam (andere Seiten waren in Ordnung). – Dan

0

Mit Blick auf Ihren Code scheint es in Ordnung. Wenn Sie jedoch weniger als die MTU senden, kann Nagles Algothrim diesen zurückhalten, bis genügend Daten für ein vollständiges Paket vorhanden sind oder Sie den Socket schließen. So

- versuchen Sie dies:

socket.setTCPNoDelay(true); 

http://en.wikipedia.org/wiki/Nagle%27s_algorithm https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#setTcpNoDelay-boolean-

+0

Hat überhaupt nicht funktioniert:/ – Neatoro

+0

Ich meinte wahr, aber diese Seite dauerte 5 Minuten, um mich zu bearbeiten. – Dan

+0

Versuchen Sie außerdem, die Zeichenfolge auf> 1500 Byte aufzufüllen. Das würde es beweisen. – Dan

0

Es ist ein Server-Problem, weil flush immer schreiben erzwingen. um es zu testen versuchen, diesen Code auszuführen:

public static void main(String[] args) throws IOException, InterruptedException { 
    Socket socket = new Socket("localhost", 8222); 
    OutputStream out = socket.getOutputStream(); 
    for (int i = 0; i < 10; i++) { 
     out.write((i + " : { \"phone\": \"23456789\" }").getBytes()); 
     out.flush(); 
     TimeUnit.SECONDS.sleep(1); 
    } 
} 

vor, diesen Befehl auf Shell ausgeführt:

$ nc -l localhost 8222 

, der auf Port 8222 für die Daten hören. Sie werden sehen, dass alle 1 Sekunde Daten auf nc Ausgang

3

ich bin sicher nicht der Kennzeichnung „// Server“ in Ihrer Frage angezeigt werden, aber ich bin den folgenden Code unter der Annahme, ist der Server-Code:

InputStream in = client.getInputStream(); 
ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 

int i = 0; 
while((i = in.read()) >= 0) { 
    bOut.write(i); 
} 

String complete = new String(bOut.toByteArray(), "UTF-8"); 

Dies wird weiter lesen, blockiert jedes Mal, bis es einen Wert von read() kleiner als Null erhält. Das passiert nur, wenn der Stream geschlossen ist.

Es sieht wirklich wie Sie benötigen ein eigenes Protokoll zu etablieren. Suchen Sie statt nach "< = 0" nach einem konstanten Wert, der das Ende der Nachricht signalisiert.

Hier ist eine kurze Demonstration dessen, was ich meine (ich hatte gestern keine Zeit). Ich habe 3 Klassen, Message, MyClient (das ist auch die main Klasse) und MyServer. Beachten Sie, dass es nichts gibt, wenn Sie einen Zeilenumbruch senden oder empfangen. Nichts setzt tcpNoDelay. Aber es funktioniert gut. Einige andere Hinweise:

  • Dieser Code sendet und empfängt nur eine einzige Anfrage und Antwort.
  • Das Senden mehrerer Instanzen Message wird nicht unterstützt. Das würde erfordern, für den Anfang eines Message sowie das Ende zu überprüfen.

Message Klasse:

public class Message { 
    public static final String MSG_START = "<message>"; 
    public static final String MSG_END = "</message>"; 

    private final String content; 

    public Message(String string){ 
     content = string; 
    } 

    @Override 
    public String toString(){ 
     return MSG_START + content + MSG_END; 
    } 
} 

MyServer Klasse

public class MyServer implements Runnable{ 
    public static final int PORT = 55555; 

    @Override 
    public void run(){ 
     try { 
      ServerSocket serverSocket = new ServerSocket(PORT); 
      Socket socket = serverSocket.accept(); 
      String message = getMessage(socket); 
      System.out.println("Server got the message: " + message); 
      sendResponse(socket); 
     }catch (IOException e){ 
      throw new IllegalStateException(e); 
     } 
    } 

    private void sendResponse(Socket socket) throws IOException{ 
     Message message = new Message("Ack"); 
     System.out.println("Server now sending a response to the client: " + message); 
     OutputStream out = socket.getOutputStream(); 
     out.write(message.toString().getBytes("UTF-8")); 
    } 

    private String getMessage(Socket socket) throws IOException{ 

     BufferedInputStream in = new BufferedInputStream(socket.getInputStream()); 
     StringBuilder sb = new StringBuilder(100); 
     byte[] bytes = new byte[1024<<8]; 
     while(sb.lastIndexOf(Message.MSG_END) == -1){ 
      int bytesRead = in.read(bytes); 
      sb.append(new String(bytes,0,bytesRead,"UTF-8")); 
     } 

     return sb.toString(); 
    } 
} 

MyClient Klasse

public class MyClient { 

    public static void main(String[] args){ 
     MyClient client = new MyClient(); 

     Thread server = new Thread(new MyServer()); 
     server.start(); 

     client.performCall(); 
    } 

    public void performCall(){ 
     try { 
      Socket socket = new Socket("127.0.0.1",MyServer.PORT); 
      sendMessage(socket, "Why hello there!"); 
      System.out.println("Client got a response from the server: " + getResponse(socket)); 
     } catch (IOException e) { 
      throw new IllegalStateException(e); 
     } 
    } 

    public String getResponse(Socket socket) throws IOException{ 
     String response; 

     StringBuilder sb = new StringBuilder(100); 
     InputStream in = socket.getInputStream(); 
     byte[] bytes = new byte[1024]; 
     while(sb.lastIndexOf(Message.MSG_END) == -1){ 
      int bytesRead = in.read(bytes); 
      sb.append(new String(bytes,0,bytesRead,"UTF-8")); 
     } 
     response = sb.toString(); 

     return response; 
    } 

    public void sendMessage(Socket socket, String message) throws IOException{ 
     Message msg = new Message(message); 
     System.out.println("Client now sending message to server: " + msg); 
     OutputStream out = socket.getOutputStream(); 
     out.write(msg.toString().getBytes("UTF-8")); 
    } 
} 

Der Ausgang

+0

Es ist nicht möglich, -1 aus dem Client-Code zu senden. Er liest in einzelnen Bytes. Solange die Verbindung nicht geschlossen wurde, kann er nur Werte zwischen 0 und 255 empfangen. Wenn der Client 'out.write (-1) 'nannte, würde der Server 255 empfangen. – SpiderPig

+0

@SpiderPig Um ehrlich zu sein, war ich nicht wirklich sicher. Ich habe vage Erinnerungen daran, das in der Vergangenheit zu tun, aber ich erinnere mich wahrscheinlich daran, dass es falsch war. Was du gesagt hast, ergibt Sinn. Ich aktualisiere meine Antwort, um sie zu reflektieren. – MadConan

0

Das Problem ist nicht, dass Sie nicht richtig gespült, sondern dass der Lesecode wartet auf die Buchse, die Daten zu trennen Vor der Inbetriebnahme:

while((i = in.read()) >= 0)

Will Schleife solange etwas gelesen werden kann von in (InputStream des Sockets). Die Bedingung wird nicht fehlschlagen, bis der andere Peer die Verbindung trennt.