Frage

Ich verwende Java.net bei einem meiner Projekte. Und ich habe einen App -Server geschrieben, der InputStream von einem Client erhält. Aber manchmal kann mein (gepufferter) InputStream nicht den gesamten Ausgangsstream erhalten, den der Client an meinen Server gesendet hat. Wie kann ich ein Warten oder so etwas schreiben, dass mein InputStream den gesamten Ausgangsstream des Clients erhält?

(Mein InputStream ist keine Zeichenfolge)

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

Vielen Dank.

War es hilfreich?

Lösung

Das Problem, das Sie haben, bezieht sich auf die TCP -Streaming -Natur.

Die Tatsache, dass Sie 100 Bytes (zum Beispiel) vom Server gesendet haben, bedeutet nicht, dass Sie beim ersten Mal 100 Bytes im Client lesen. Vielleicht kommen die vom Server gesendeten Bytes in mehreren TCP -Segmenten an den Client an.

Sie müssen eine Schleife implementieren, in der Sie lesen, bis die gesamte Nachricht empfangen wurde. Lassen Sie mich ein Beispiel mit geben DataInputStream Anstatt von BufferedinputStream. Etwas sehr Einfaches, um Ihnen nur ein Beispiel zu geben.

Nehmen wir an, Sie wissen zuvor, dass der Server 100 Bytes Daten senden soll.

Im Kunden müssen Sie schreiben:

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

In der Regel ist die Datengröße, die von einem Knoten (dem Server hier) gesendet wurde, vorher nicht bekannt. Anschließend müssen Sie Ihr eigenes kleines Protokoll für die Kommunikation zwischen Server und Client (oder zwei Knoten) definieren, die mit TCP kommunizieren.

Am häufigsten und einfachsten besteht darin, TLV zu definieren: Typ, Länge, Wert. Daher definieren Sie, dass jeder mit dem Meldung gesendete Formular Server an Client mit:

  • 1 Byte angibt den Typ (zum Beispiel könnte es auch 2 oder was auch immer sein).
  • 1 Byte (oder was auch immer) für die Länge der Nachricht
  • N Bytes für den Wert (n ist in Länge angezeigt).

Sie wissen also, dass Sie mindestens 2 Bytes erhalten müssen, und mit dem zweiten Byte wissen Sie, wie viele folgende Bytes Sie lesen müssen.

Dies ist nur ein Vorschlag eines möglichen Protokolls. Sie können auch "Typ" loswerden.

Es wäre also so etwas wie:

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

Der folgende Code kompiliert und sieht besser aus. Es wird angenommen, dass die ersten beiden Bytes, die die Länge im binären Format in Network Endianship (Big Endian) ankommen, angeben. Kein Fokus auf verschiedene Codierungstypen für den Rest der Nachricht.

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

Andere Tipps

Sie können Ihren BufferedInputStream so lesen. Es wird Daten gelesen, bis es das Ende des Streams erreicht, der durch -1 angezeigt wird.

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 () zeigt die verfügbaren Bytes erst nach dem Lesen eines Byte, weshalb es .. während

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top