Come leggere tutto di Inputstream in Server Socket JAVA

Sto usando Java.net in uno dei miei progetti. e ho scritto un App Server che riceve inputStream da un client. Ma alcune volte il mio InputStream (bufferizzato) non riesce a ottenere tutto OutputStream che il client ha inviato al mio server. Come posso scrivere un’attesa o qualcosa del genere, che il mio InputStream ottenga tutto l’OutputStream del client?

(My InputStream non è una stringa)

private Socket clientSocket; private ServerSocket server; private BufferedOutputStream outputS; private BufferedInputStream inputS; private InputStream inBS; private OutputStream outBS; server = new ServerSocket(30501, 100); clientSocket = server.accept(); public void getStreamFromClient() { try { outBS = clientSocket.getOutputStream(); outputS = new BufferedOutputStream( outBS); outputS.flush(); inBS = clientSocket.getInputStream(); inputS = new BufferedInputStream( inBS ); } catch (Exception e) { e.printStackTrace(); } } 

Grazie.

Il problema che hai è legato alla natura dello streaming TCP.

Il fatto che tu abbia inviato 100 byte (ad esempio) dal server non significa che leggerai 100 byte nel client la prima volta che leggerai. Forse i byte inviati dal server arrivano in diversi segmenti TCP al client.

È necessario implementare un ciclo in cui si legge finché non è stato ricevuto l’intero messaggio. Consentitemi di fornire un esempio con DataInputStream invece di BufferedinputStream . Qualcosa di molto semplice per darti solo un esempio.

Supponiamo che tu sappia in anticipo che il server deve inviare 100 byte di dati.

Nel client è necessario scrivere:

 byte[] messageByte = new byte[1000]; boolean end = false; String dataString = ""; try { DataInputStream in = new DataInputStream(clientSocket.getInputStream()); while(!end) { int bytesRead = in.read(messageByte); dataString += new String(messageByte, 0, bytesRead); if (dataString.length == 100) { end = true; } } System.out.println("MESSAGE: " + dataString); } catch (Exception e) { e.printStackTrace(); } 

Ora, in genere la dimensione dei dati inviati da un nodo (il server qui) non è nota in anticipo. Quindi è necessario definire il proprio piccolo protocollo per la comunicazione tra server e client (o qualsiasi due nodes) che comunichi con TCP.

Il più comune e semplice è definire TLV: Type, Length, Value. Così definisci che ogni messaggio inviato dal server al client viene fornito con:

  • 1 byte che indica il tipo (ad esempio, potrebbe anche essere 2 o qualsiasi altra cosa).
  • 1 byte (o qualsiasi altra cosa) per la lunghezza del messaggio
  • N byte per il valore (N è indicato in lunghezza).

Quindi sai che devi ricevere almeno 2 byte e con il secondo byte sai quanti byte hai bisogno di leggere.

Questo è solo un suggerimento di un ansible protocollo. Potresti anche sbarazzarti di “Type”.

Quindi sarebbe qualcosa di simile:

 byte[] messageByte = new byte[1000]; boolean end = false; String dataString = ""; try { DataInputStream in = new DataInputStream(clientSocket.getInputStream()); int bytesRead = 0; messageByte[0] = in.readByte(); messageByte[1] = in.readByte(); int bytesToRead = messageByte[1]; while(!end) { bytesRead = in.read(messageByte); dataString += new String(messageByte, 0, bytesRead); if (dataString.length == bytesToRead ) { end = true; } } System.out.println("MESSAGE: " + dataString); } catch (Exception e) { e.printStackTrace(); } 

Il seguente codice viene compilato e sembra migliore. Si presuppone che i primi due byte forniscano la lunghezza in formato binario, in endianship di rete (big endian). Nessun focus su diversi tipi di codifica per il resto del messaggio.

 import java.nio.ByteBuffer; import java.io.DataInputStream; import java.net.ServerSocket; import java.net.Socket; class Test { public static void main(String[] args) { byte[] messageByte = new byte[1000]; boolean end = false; String dataString = ""; try { Socket clientSocket; ServerSocket server; server = new ServerSocket(30501, 100); clientSocket = server.accept(); DataInputStream in = new DataInputStream(clientSocket.getInputStream()); int bytesRead = 0; messageByte[0] = in.readByte(); messageByte[1] = in.readByte(); ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, 2); int bytesToRead = byteBuffer.getShort(); System.out.println("About to read " + bytesToRead + " octets"); //The following code shows in detail how to read from a TCP socket while(!end) { bytesRead = in.read(messageByte); dataString += new String(messageByte, 0, bytesRead); if (dataString.length() == bytesToRead ) { end = true; } } //All the code in the loop can be replaced by these two lines //in.readFully(messageByte, 0, bytesToRead); //dataString = new String(messageByte, 0, bytesToRead); System.out.println("MESSAGE: " + dataString); } catch (Exception e) { e.printStackTrace(); } } } 

Puoi leggere il tuo BufferedInputStream in questo modo. Legge i dati fino a raggiungere la fine del stream, che è indicato da -1.

 inputS = new BufferedInputStream(inBS); byte[] buffer = new byte[1024]; //If you handle larger data use a bigger buffer size int read; while((read = inputS.read(buffer)) != -1) { System.out.println(read); // Your code to handle the data } 
 int c; String raw = ""; do { c = inputstream.read(); raw+=(char)c; } while(inputstream.available()>0); 

InputStream.available () mostra i byte disponibili solo dopo che un byte è stato letto, quindi do … while