J'écris une application .NET qui fera un appel RPC à une application Java (via une file d'attente de messages). Les données envoyées dans les deux directions seront de grands tableaux de nombres à virgule flottante. Quelle est la meilleure façon de les sérialiser pour les envoyer sur le câble ? J'aimerais quelque chose de plus compact qu'un texte, mais indépendant de l'architecture car le serveur n'est pas forcément une machine x86. L'application Java peut être modifiée si nécessaire.
Réponses
Trop de publicités?Les primitives numériques Java sont en fait stockées (dans la JVM) et écrites (par l'intermédiaire de jnava.io.DataOutputStream
y java.nio.ByteBuffer
) dans l'ordre du réseau et les valeurs à virgule flottante sont conformes à la norme IEEE. Ils sont directement interchangeables avec C#/.NET. Enfin, si .NET fournissait l'ordre des octets du réseau pour lire les doubles (voir le code ci-dessous).
Vous pouvez donc envoyer et recevoir n'importe quelle primitive en utilisant les deux classes mentionnées ici (et leurs homologues d'entrée) tant que le côté .NET lit/écrit dans l'ordre des octets du réseau, comme vous devriez toujours le faire.
Côté Java par exemple :
// Assume the following somewhere in your class
Socket socket;
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
// Send a double
out.writeDouble(doubleValue);
C# pour récupérer la valeur :
Stream stream = new NetworkStream(socket, FileAccess.ReadWrite, true);
BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);
// Read double from the stream
long v = IPAddress.NetworkToHostOrder(reader.ReadInt64());
double doubleValue = BitConverter.Int64BitsToDouble(v);
Pour l'écriture, vous faites l'inverse, C# doit écrire dans l'ordre des octets du réseau.
Stream stream = new NetworkStream(socket, FileAccess.ReadWrite, true);
BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8);
// Write double to the stream
long v = BitConverter.DoubleToInt64Bits(doubleValue);
writer.Write(IPAddress.HostToNetworkOrder(v));
Puis, du côté de Java, pour les relire :
// Some where in your class
Socket socket;
DataInputStream in = new DataInputStream(socket.getInputStream());
// To read the double
double doubleValue = in.readDouble();
Le programme C# IPAddress
fournit des méthodes de lecture/écriture dans l'ordre des octets du réseau pour toutes les primitives, à l'exception de double et float, mais comme dans mon exemple, vous pouvez passer par un int 32 bits ou 64 bits respectivement.
Je suis en train de lire sur Tampons de protocole et ils semblent prometteurs. Il existe une implémentation officielle de Google pour Java et une implémentation de Portage en C# par nul autre que Jon Skeet.