Domanda

Sto usando java.net in uno dei miei progetti. E ho scritto un server di app che ottiene InputStream da un client. Ma alcune volte il mio inputstream (buffer) non può ottenere tutto il client inviato al mio server. Come posso scrivere un'attesa o una cosa del genere, che il mio inputstream ottiene tutto il STRESTROUM OUTPUT del client?

(Il mio 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.

È stato utile?

Soluzione

Il problema che hai è correlato alla natura di 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 leggi. Forse i byte inviati dal server arrivano in diversi segmenti TCP al client.

È necessario implementare un ciclo in cui leggi fino a quando l'intero messaggio non è stato ricevuto. Fammi fornire un esempio con DataInputStream invece di BufferedinputStream. Qualcosa di molto semplice da darti solo un esempio.

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

Nel client devi 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 inviata 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 due nodi) che comunica con TCP.

Il più comune e semplice è definire TLV: tipo, lunghezza, valore. Quindi si definisce che ogni messaggio inviato al client viene fornito con:

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

Quindi sai che devi ricevere un minimo di 2 byte e con il secondo byte sai quanti byte seguenti devi leggere.

Questo è solo un suggerimento di un possibile protocollo. Potresti anche sbarazzarti del "tipo".

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 compila e sembra migliore. Presuppone che i primi due byte forniscano la lunghezza arrivano in formato binario, in Network Endianship (Big Endian). Nessuna attenzione 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();
        }
    }
}

Altri suggerimenti

Puoi leggere il tuo bufferedInputStream in questo modo. Leggerà i dati fino a quando non raggiungerà il flusso 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 aver letto un byte, quindi fai .. mentre

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top