Question

J'utilise java.net dans l'un de mes projets. Et j'ai écrit un serveur d'applications qui obtient InputStream d'un client. Mais parfois, mon (tampon) InputStream ne peut pas obtenir tout ce que le client a envoyé à mon serveur. Comment puis-je écrire une attente ou quelque chose comme ça, que mon entréestre a tout le nombre de sorties de client?

(Mon inputStream n'est pas une chaîne)

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

Merci.

Était-ce utile?

La solution

Le problème que vous avez est lié à la nature en streaming TCP.

Le fait que vous ayez envoyé 100 octets (par exemple) du serveur ne signifie pas que vous lirez 100 octets dans le client la première fois que vous lisez. Peut-être que les octets envoyés du serveur arrivent dans plusieurs segments TCP au client.

Vous devez implémenter une boucle dans laquelle vous lisez jusqu'à ce que l'ensemble du message soit reçu. Permettez-moi de fournir un exemple avec DataInputStream à la place de BufferedinputStream. Quelque chose de très simple à vous donner juste un exemple.

Supposons que vous sachiez à l'avance que le serveur doit envoyer 100 octets de données.

Dans le client, vous devez écrire:

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

Désormais, la taille des données envoyée par un nœud (le serveur ici) n'est généralement pas connu à l'avance. Ensuite, vous devez définir votre propre petit protocole pour la communication entre le serveur et le client (ou deux nœuds) communiquant avec TCP.

Le plus courant et le plus simple est de définir TLV: type, longueur, valeur. Vous définissez donc que chaque serveur de formulaire envoyé par message est livré avec:

  • 1 octet indiquant le type (par exemple, il pourrait aussi être 2 ou autre).
  • 1 octet (ou autre) pour la durée du message
  • N octets pour la valeur (n est indiqué en longueur).

Vous savez donc que vous devez recevoir un minimum de 2 octets et avec le deuxième octet, vous savez combien d'octets suivants vous devez lire.

Ce n'est qu'une suggestion d'un protocole possible. Vous pouvez également vous débarrasser du "type".

Ce serait donc quelque chose comme:

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

Le code suivant compile et a l'air mieux. Il suppose que les deux premiers octets fournissant la longueur arrivent au format binaire, dans Network Endianhip (Big Endian). Aucune concentration sur différents types d'encodage pour le reste du message.

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

Autres conseils

Vous pouvez lire votre BufferedInputStream comme ceci. Il lira les données jusqu'à ce qu'elle atteigne la fin du flux qui est indiquée par -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 () montre les octets disponibles uniquement après qu'un octet est lu, donc faire ..

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top