comment envoyer un tableau d'octets sur une connexion TCP (programmation java)
Quelqu'un peut-il montrer comment envoyer un tableau d'octets sur une connexion TCP d'un programme expéditeur à un programme récepteur en Java.
byte[] myByteArray
(je suis nouveau à la programmation Java, et n'arrive pas à trouver un exemple de comment faire cela qui montre les deux extrémités de la connexion (expéditeur et récepteur.) Si vous connaissez un exemple existant, peut-être que vous pourriez poster le lien. (Pas besoin de réinventer la roue.) P.S. C'est Pas devoirs! :-)
9 réponses
Les classes InputStream
et OutputStream
en Java gèrent nativement les tableaux d'octets. La seule chose que vous pouvez ajouter est la longueur au début du message afin que le récepteur sache combien d'octets attendre. J'aime généralement offrir une méthode qui permet de contrôler les octets du tableau d'octets à envoyer, tout comme l'API standard.
Quelque Chose comme ceci:
private Socket socket;
public void sendBytes(byte[] myByteArray) throws IOException {
sendBytes(myByteArray, 0, myByteArray.length);
}
public void sendBytes(byte[] myByteArray, int start, int len) throws IOException {
if (len < 0)
throw new IllegalArgumentException("Negative length not allowed");
if (start < 0 || start >= myByteArray.length)
throw new IndexOutOfBoundsException("Out of bounds: " + start);
// Other checks if needed.
// May be better to save the streams in the support class;
// just like the socket variable.
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
dos.writeInt(len);
if (len > 0) {
dos.write(myByteArray, start, len);
}
}
EDIT: Pour ajouter le côté réception:
public byte[] readBytes() throws IOException {
// Again, probably better to store these objects references in the support class
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
int len = dis.readInt();
byte[] data = new byte[len];
if (len > 0) {
dis.readFully(data);
}
return data;
}
Il suffit de commencer par cet exemple du vraiment grand Index. Notez cependant qu'il est conçu pour transmettre et recevoir des caractères, pas d'octets. Ce n'est pas une grosse affaire, cependant - vous pouvez simplement traiter les objets InputStream
et OutputStream
bruts que la classe Socket
fournit. Voir L'API pour plus d'informations sur les différents types de lecteurs, écrivains et flux. Les méthodes qui vous intéresseront sont OutputStream.write(byte[])
et InputStream.read(byte[])
.
Le tutoriel de communication Oracle socket semble être le point de lancement approprié.
Notez qu'il va problème supplémentaire pour transformer les caractères en octets. Si vous voulez travailler au niveau des octets, Décollez-le.
Ce Soleil Sockets tutoriel devrait vous donner un bon point de départ
Ce que vous devez utiliser est le write
méthode de java.io.OutputStream
et le read
méthode de java.io.InputStream
, à la fois de laquelle vous pouvez récupérer à partir de la Socket
vous ouvrez.
Je vous demande D'utiliser ObjectOutputStream et ObjectInputStream. Ceux-ci envoient tout comme un objet et reçoivent comme le même.
ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
os.flush();
ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
os.writeObject(byte_array_that_you_want_to_send);
byte[] temp = (byte[]) is.readObject();
Rappelez-vous également de créer d'abord le flux de sortie, de le vider, puis d'aller de l'avant avec le flux d'entrée, car si quelque chose est laissé dans le flux, le flux d'entrée ne sera pas créé.
Je suppose que la question est mal formulée. J'ai trouvé cela lors de la recherche d'une réponse à la raison pour laquelle mon utilisation de InputStream et OutputStream semblait définir le tableau entier à 0 en rencontrant un octet de valeur 0. Est-ce que ceux-ci supposent que les octets contiennent ASCII valide et non binaire. Puisque la question ne vient pas tout de suite et pose ceci, et personne d'autre ne semble l'avoir pris comme une possibilité, je suppose que je vais devoir satisfaire ma quête ailleurs.
Ce que j'essayais de faire était d'écrire une classe TransparentSocket qui peut instancier soit un TCP (Socket / ServerSocket) ou un UDP (DatagramSocket) pour utiliser le DatagramPacket de manière transparente. Cela fonctionne pour UDP, mais pas (encore) pour TCP.
Suivi: il me semble avoir vérifié que ces flux sont eux-mêmes inutiles pour les transferts binaires, mais qu'ils peuvent être passés à une instanciation plus conviviale pour le programmeur, par exemple,
Nouveau DataOutputStream(socket.getOutputStream ()).writeInt(5);
^ tellement pour cette idée. Il écrit des données de manière "portable", c'est-à-dire, probablement ASCII, ce qui n'est d'aucune aide, surtout lors de l'émulation de logiciels sur lesquels je n'ai aucun contrôle!
import java.io.*;
import java.net.*;
public class ByteSocketClient
{
public static void main(String[] args) throws UnknownHostException, IOException
{
Socket s=new Socket("",6000);
DataOutputStream dout=new DataOutputStream(new BufferedOutputStream(s.getOutputStream()));
byte[] a = {(byte)0xC0,(byte)0xA8,(byte)0x01,(byte)0x02,(byte)0x53,(byte)0x4D,(byte)0x41,(byte)0x52,(byte)0x54};
dout.write(a);
dout.close();
s.close();
}
}
Voici un exemple qui diffuse des trames de fichiers WAV de 100 octets à la fois.
private Socket socket;
public void streamWav(byte[] myByteArray, int start, int len) throws IOException {
Path path = Paths.get("path/to/file.wav");
byte[] data = Files.readAllBytes(path);
OutputStream out = socket.getOutputStream();
DataOutputStream os = new DataOutputStream(out);
os.writeInt(len);
if (len > 0) {
os.write(data, start, len);
}
}
public void readWav() throws IOException {
InputStream in = socket.getInputStream();
int frameLength = 100; // use useful number of bytes
int input;
boolean active = true;
while(active) {
byte[] frame = new byte[frameLength];
for(int i=0; i<frameLength; i++) {
input = in.read();
if(input < 0) {
active = false;
break;
} else frame[i] = (byte) input;
}
// playWavPiece(frame);
// streamed frame byte array is full
// use it here ;-)
}
}