J'utilise Java.net sur l'un de mes projets. et j'ai écrit un serveur d'applications qui reçoit inputStream d'un client. Mais parfois, mon InputStream (mis en mémoire tampon) ne peut pas obtenir tous les OutputStream que le client a envoyés à mon serveur. Comment puis-je écrire une attente ou quelque chose comme ça, que mon InputStream obtient tout le OutputStream du 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.
Le problème que vous rencontrez est lié à TCP nature du streaming.
Le fait que vous ayez envoyé 100 octets (par exemple) à partir du serveur ne signifie pas que vous lirez 100 octets dans le client la première fois que vous lirez. Peut-être que les octets envoyés par le serveur arrivent dans plusieurs segments TCP au client.
Vous devez implémenter une boucle dans laquelle vous lisez jusqu'à ce que le message entier ait été reçu. Permettez-moi de fournir un exemple avec DataInputStream
au lieu de BufferedinputStream
. Quelque chose de très simple pour vous donner juste un exemple.
Supposons que vous sachiez au préalable 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ées par un nœud (le serveur ici) n'est généralement pas connue à 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.
La plus courante et la plus simple consiste à définir TLV: Type, Longueur, Valeur. Vous définissez donc que chaque message envoyé par le serveur de formulaire au client est livré avec:
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 de "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 semble meilleur. Il suppose les deux premiers octets à condition que la longueur arrive au format binaire, en endianship réseau (big endian). Aucun accent sur les 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();
}
}
}
int c;
String raw = "";
do {
c = inputstream.read();
raw+=(char)c;
} while(inputstream.available()>0);
InputStream.available () affiche les octets disponibles uniquement après la lecture d'un octet.
Vous pouvez lire votre BufferedInputStream comme ceci. Il lira les données jusqu'à ce qu'il atteigne la fin du flux, ce qui est indiqué 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
}