Quelqu'un peut-il expliquer comment envoyer un tableau d'octets via une connexion TCP d'un programme émetteur à un programme récepteur en Java?.
byte[] myByteArray
(Je suis nouveau dans la programmation Java et je n'arrive pas à trouver un exemple montrant comment faire cela et qui montre les deux extrémités de la connexion (expéditeur et destinataire.) Si vous connaissez un exemple existant, vous pouvez peut-être publier le lien. . (Pas besoin de réinventer la roue.) PS Ceci estPASdevoirs! :-)
Les classes InputStream
et OutputStream
de Java gèrent nativement les tableaux d'octets. Vous voudrez peut-être ajouter la longueur au début du message pour que le destinataire sache le nombre d'octets à attendre. En général, j'aime proposer une méthode qui permet de contrôler quels octets du tableau d'octets envoyer, un peu comme l'API standard.
Quelque chose comme ça:
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é destinataire:
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;
}
Commencez simplement par cet exemple du Really Big Index . Notez cependant qu'il est conçu pour transmettre et recevoir des caractères, pas des octets. Ce n'est pas grave, cependant - vous pouvez simplement gérer les objets bruts InputStream
et OutputStream
fournis par la classe Socket
. Consultez l'API pour plus d'informations sur les différents types de lecteurs, d'écrivains et de flux. Les méthodes qui vous intéresseront sont OutputStream.write(byte[])
et InputStream.read(byte[])
.
Le didacticiel Oracle Socket Communications semble être le point de départ approprié.
Notez que ça va extra trouble pour transformer les caractères en octets. Si vous voulez travailler au niveau octet, décollez-le.
Ce tutoriel Sun Sockets devrait vous donner un bon point de départ.
Je vous demanderais d’utiliser ObjectOutputStream et ObjectInputStream. Ceux-ci envoient tout comme un objet et reçoivent 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();
Souvenez-vous également de créer d’abord le flux de sortie, de le vider, puis de poursuivre avec le flux d’entrée, car si quelque chose restait dans le flux, le flux d’entrée ne serait pas créé.
Ce que vous devez utiliser est la méthode write
d'un Java.io.OutputStream
et la méthode read
d'un Java.io.InputStream
, que vous pouvez récupérer à partir de la Socket
que vous ouvrez.
Voici un exemple qui diffuse des images de fichier 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 ;-)
}
}
Je suppose que la question est mal formulée. Je trouvais cela en cherchant une réponse à la question de savoir pourquoi mon utilisation de InputStream et OutputStream semblait mettre l'ensemble du tableau à 0 lorsque je rencontrais un octet de valeur 0. Cela suppose-t-il que les octets contiennent ASCII valide et non binaire. Étant donné que la question ne vient pas directement et ne pose pas cette question, et que personne d'autre ne semble l'avoir comprise comme une possibilité, je suppose que je devrai satisfaire ma quête ailleurs.
Ce que j’essayais de faire, c’était d’écrire une classe TransparentSocket pouvant instancier un TCP (Socket/ServerSocket) ou un UDP (DatagramSocket) pour utiliser le paquet DatagramPacket de manière transparente. Cela fonctionne pour UDP, mais pas (encore) pour TCP.
Suivi: Je semble avoir vérifié que ces flux sont eux-mêmes inutiles pour les transferts binaires, mais qu’ils peuvent être transmis à une instanciation plus conviviale pour les programmeurs, par exemple,
nouveau DataOutputStream (socket.getOutputStream ()). writeInt (5);
^ Voilà pour cette idée. Il écrit les données de manière "portable", c'est-à-dire probablement ASCII, ce qui n'est d'aucune aide, en particulier pour émuler un logiciel sur lequel 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();
}
}