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

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

// ServerJava OutputStream svuota solo i dati su una stretta

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"); 

avevo cercato di inviare dati tramite OutputStream ad una presa di corrente, ma i dati non sono vampate di calore. Se aggiungo un out.close(); alla fine, funziona perfettamente, ma il socket è chiuso e non posso accettare la risposta. Qualcuno sa perché? Il server non sta dando alcun tipo di errore. Ho usato Java 1.7!

+0

Che aspetto ha il codice server? – Dan

+0

Come hai confermato che l'output non è stato inviato? – Simon

+1

Beh, sai, un 'OutputStream' ha' .flush() '. Inoltre, il modo in cui scrivi il tuo JSON è rotto: utilizza la codifica predefinita di JRE. Perché non usi invece una libreria JSON? – fge

risposta

6

È possibile che il server sia in attesa della fine della riga. Se questo è il caso aggiungere "\ n" per il testo

+0

Questa era esattamente la cosa che stava facendo il mio programma. Grazie per il consiglio! – gdawgrancid

1

Provare a utilizzare

socket.setTcpNoDelay(true); 

C'è buffer che si verifica per motivi di prestazioni (leggere su l'algoritmo di Nagle).

+0

Grandi menti :) Ho provato a postare prima di te ma questo sito ha iniziato ad andare veramente lento (altri siti andavano bene). – Dan

0

Guardando il tuo codice sembra ok. Comunque tu stai inviando meno del MTU Nagle's algothrim potrebbe trattenerlo fino a quando non saranno presenti abbastanza dati per un pacchetto completo o chiuderai il socket.

Quindi - provare questo:

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

Non ha funzionato affatto:/ – Neatoro

+0

intendevo vero ma questo sito impiegava 5 minuti per permettermi di modificarlo. – Dan

+0

Prova anche a estendere la stringa a> 1500 byte. Questo lo proverebbe. – Dan

0

Si tratta di un problema del server, perché flush costringono sempre a scrivere. di testarlo provare a eseguire questo codice:

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); 
    } 
} 

prima, eseguire questo comando sul guscio:

$ nc -l localhost 8222 

che ascolto sulla porta 8222 per i dati. si vedrà che ogni 1 secondo dati visualizzato sul nc uscita

3

Non sono sicuro che l'etichettatura "// Server" nella tua domanda, ma sto assumendo il seguente codice è il codice del server:

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"); 

Continuerà a leggere, bloccando ogni volta, finché non ottiene un valore da read() inferiore a zero. Questo succede solo se lo stream è chiuso.

Sembra davvero che sia necessario stabilire il proprio protocollo. Quindi, anziché cercare "< = 0", cerca un valore costante che segnali la fine del messaggio.

Ecco una rapida dimostrazione di cosa intendo (non ho avuto tempo ieri). Ho 3 classi, Message, MyClient (che è anche la classe main) e MyServer. Si noti che non c'è nulla riguardo l'invio o la ricezione di una nuova riga. Nulla sta impostando tcpNoDelay. Ma funziona bene. Alcune altre note:

  • Questo codice invia e riceve solo una singola richiesta e risposta.
  • Non supporta l'invio di più istanze Message. Ciò richiederebbe il controllo per l'inizio di un Message così come la fine.

Message classe:

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 classe

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 classe

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")); 
    } 
} 

L'uscita

Client now sending message to server: Why hello there! 
Server got the message: Why hello there! 
Server now sending a response to the client: Ack 
Client got a response from the server: Ack 

Process finished with exit code 0
+0

Non è possibile inviare -1 dal codice cliente. Sta leggendo in singoli byte. Finché la connessione non è stata chiusa, può ricevere solo valori compresi tra 0 e 255. Se il client chiama 'out.write (-1)' il server riceverà 255. – SpiderPig

+0

@SpiderPig Per essere onesti, non ero veramente sicuro. Ho vaghi ricordi di averlo fatto in passato, ma probabilmente sto ricordando che è sbagliato. Quello che hai detto ha senso. Sto aggiornando la mia risposta per rifletterlo. – MadConan

0

Il problema non è che non si sta lavando correttamente, ma che il codice di lettura attende rete per disinserire prima di manipolare i dati:

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

Will ciclo fintanto che qualcosa si può leggere da in (InputStream del socket). La condizione non fallirà fino a quando l'altro peer si disconnette.

Problemi correlati