Pregunta

Estoy usando java.net en uno de mi proyecto. Y escribí un servidor de aplicaciones que obtiene InputStream de un cliente. Pero algunas veces mi InputStream (buffered) no puede obtener todo el OutputStream que el cliente envió a mi servidor. ¿Cómo puedo escribir una espera o algo así, que mi InputStream obtiene toda la salida del cliente?

(Mi InputStream no es una cadena)

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

Gracias.

¿Fue útil?

Solución

El problema que tiene está relacionado con la naturaleza de transmisión de TCP.

El hecho de que haya enviado 100 bytes (por ejemplo) del servidor no significa que leerá 100 bytes en el cliente la primera vez que lea. Tal vez los bytes enviados desde el servidor llegan en varios segmentos TCP al cliente.

Debe implementar un bucle en el que lea hasta que se recibió todo el mensaje. Déjame proporcionar un ejemplo con DataInputStream en vez de BufferedinputStream. Algo muy simple de darte solo un ejemplo.

Supongamos que sabes de antemano que el servidor debe enviar 100 bytes de datos.

En el cliente debe escribir:

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

Ahora, por lo general, el tamaño de datos enviado por un nodo (el servidor aquí) no se conoce de antemano. Luego, debe definir su propio protocolo pequeño para la comunicación entre el servidor y el cliente (o dos nodos) comunicándose con TCP.

El más común y simple es definir TLV: tipo, longitud, valor. Por lo tanto, define que cada mensaje enviado servidor al cliente viene con:

  • 1 byte indicando tipo (por ejemplo, también podría ser 2 o lo que sea).
  • 1 byte (o lo que sea) para la longitud del mensaje
  • N bytes para el valor (n se indica en longitud).

Entonces, sabe que debe recibir un mínimo de 2 bytes y con el segundo byte sabe cuántos bytes siguientes necesita leer.

Esto es solo una sugerencia de un posible protocolo. También podría deshacerse del "tipo".

Entonces sería algo como:

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

El siguiente código se compila y se ve mejor. Se supone que los dos primeros bytes que proporcionan la longitud llegan en formato binario, en la endianismo de red (Big Endian). No se centra en diferentes tipos de codificación para el resto del mensaje.

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

Otros consejos

Puede leer su BufferedInputStream así. Leerá datos hasta que llegue al final de la transmisión que se indica en -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 () muestra los bytes disponibles solo después de que se lea un byte, por lo tanto, mientras lo haga ... mientras

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top