Pergunta

Estou usando o java.net em um dos meus projetos. E escrevi um servidor de aplicativos que recebe o InputStream de um cliente. Mas algumas vezes meu InputStream (em buffer) não pode obter todo o UatingStream que o cliente enviou ao meu servidor. Como posso escrever uma espera ou algo assim, que meu InputStream obtém toda a forma de saída do cliente?

(Meu inputstream não é uma string)

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

Obrigado.

Foi útil?

Solução

O problema que você tem está relacionado à natureza do streaming de TCP.

O fato de você ter enviado 100 bytes (por exemplo) do servidor não significa que você lerá 100 bytes no cliente na primeira vez que ler. Talvez os bytes enviados do servidor cheguem em vários segmentos TCP para o cliente.

Você precisa implementar um loop no qual lê até que toda a mensagem fosse recebida. Deixe -me fornecer um exemplo com DataInputStream ao invés de BufferedinputStream. Algo muito simples para lhe dar apenas um exemplo.

Suponhamos que você saiba de antemão o servidor é enviar 100 bytes de dados.

No cliente, você precisa escrever:

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

Agora, normalmente o tamanho dos dados enviado por um nó (o servidor aqui) não é conhecido de antemão. Em seguida, você precisa definir seu próprio pequeno protocolo para a comunicação entre servidor e cliente (ou quaisquer dois nós) se comunicando com o TCP.

O mais comum e simples é definir TLV: tipo, comprimento, valor. Então você define que cada mensagem enviou o servidor de formulário para o cliente vem com:

  • 1 byte indicando tipo (por exemplo, também pode ser 2 ou qualquer outra coisa).
  • 1 byte (ou qualquer outra coisa) para a duração da mensagem
  • N bytes para o valor (n é indicado em comprimento).

Então você sabe que precisa receber um mínimo de 2 bytes e, com o segundo byte, você sabe quantos bytes seguintes você precisa ler.

Esta é apenas uma sugestão de um possível protocolo. Você também pode se livrar de "tipo".

Então seria 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();
}

O código a seguir compila e parece melhor. Ele pressupõe que os dois primeiros bytes, proporcionando o comprimento, chegam em formato binário, na endiance de rede (Big Endian). Nenhum foco em diferentes tipos de codificação para o restante da mensagem.

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

Outras dicas

Você pode ler seu bufferInputStream assim. Ele lerá dados até atingir o final do fluxo, indicado por -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 os bytes disponíveis somente depois que um byte é lido, daí ... enquanto

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top