2017-09-11 4 views
1

Je dois communiquer entre Java et C# où je dois envoyer un objet via le serveur socket. Ici, la partie serveur est écrite en Java et la partie Client est écrite en C#. Je veux envoyer un objet du serveur (Java) et le recevoir dans le client (C#). Mais je ne peux pas le faire.Transférer un objet de Java en C#

LocalJobInfo.java:

package testsocket; 

import java.io.Serializable; 

public class LocalJobInfo implements Serializable{ 
    private String id; 
    private String message; 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public void setMessage(String message) { 
     this.message = message; 
    } 
} 

serveur (en Java):

List<LocalJobInfo> jobInfoList = new ArrayList<LocalJobInfo>(); 
LocalJobInfo jobInfo = new LocalJobInfo(); 

jobInfo.setId("1"); 
jobInfo.setMessage("Success"); 

jobInfoList.add(jobInfo); 

ServerSocket serverSocket = new ServerSocket(4343, 10); 
Socket socket = serverSocket.accept(); 
InputStream is = null; 
OutputStream os = null; 
String received = null; 
try { 
     is = socket.getInputStream(); 
     os = socket.getOutputStream(); 
     byte[] lenBytes = new byte[4]; 
     is.read(lenBytes, 0, 4); 
     int len = (((lenBytes[3] & 0xff) << 24) | ((lenBytes[2] & 0xff) << 16) 
     | ((lenBytes[1] & 0xff) << 8) | (lenBytes[0] & 0xff)); 
     byte[] receivedBytes = new byte[len]; 
     is.read(receivedBytes, 0, len); 
     received = new String(receivedBytes, 0, len); 


     System.out.println("Server received: " + received); 

     // Sending 

     byte[] toSendBytes = null; 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     ObjectOutput out = null; 
     try { 
       out = new ObjectOutputStream(bos); 
       out.writeObject(jobInfoList); 
       out.flush(); 
       toSendBytes = bos.toByteArray(); 
     } finally { 
        try { 
         bos.close(); 
        } catch (IOException ex) { 
         // ignore close exception 
        } 
     } 

     int toSendLen = toSendBytes.length; 
     byte[] toSendLenBytes = new byte[4]; 
     toSendLenBytes[0] = (byte) (toSendLen & 0xff); 
     toSendLenBytes[1] = (byte) ((toSendLen >> 8) & 0xff); 
     toSendLenBytes[2] = (byte) ((toSendLen >> 16) & 0xff); 
     toSendLenBytes[3] = (byte) ((toSendLen >> 24) & 0xff); 
     os.write(toSendLenBytes); 
     os.write(toSendBytes); 

     try { 
       Thread.sleep(10000); 
     } catch (Exception ex) { 
     } 
    } catch (Exception ex) { 
    } 
    socket.close(); 
    serverSocket.close(); 

client (en C#):

string toSend = "Hello!"; 

IPEndPoint serverAddress = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4343); 

Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
clientSocket.Connect(serverAddress); 

// Sending 
int toSendLen = System.Text.Encoding.ASCII.GetByteCount(toSend); 
byte[] toSendBytes = System.Text.Encoding.ASCII.GetBytes(toSend); 
byte[] toSendLenBytes = System.BitConverter.GetBytes(toSendLen); 
clientSocket.Send(toSendLenBytes); 
clientSocket.Send(toSendBytes); 

// Receiving 
byte[] rcvLenBytes = new byte[4]; 
clientSocket.Receive(rcvLenBytes); 
int rcvLen = System.BitConverter.ToInt32(rcvLenBytes, 0); 
byte[] rcvBytes = new byte[rcvLen]; 
clientSocket.Receive(rcvBytes); 

MemoryStream memStream = new MemoryStream(); 
BinaryFormatter binForm = new BinaryFormatter(); 
memStream.Write(rcvBytes, 0, rcvBytes.Length); 
memStream.Seek(0, SeekOrigin.Begin); 
Object obj = (Object)binForm.Deserialize(memStream); 

J'ai reçu une exception lors de la désérialisation de l'octet [] dans le client C#. Le message d'exception est: "Le flux d'entrée n'est pas un format binaire valide dont le contenu de départ (en octets) est: AC-ED-00-05-73-72-00-17-74-65-73-74- 73-6F-63-6B-65 ... "

Maintenant, ma question est, comment puis-je résoudre le problème afin de désérialiser en code C# et obtenir l'objet envoyé par le serveur en Java?

+4

Utilisez une représentation de protocole intermédiaire partagée de l'objet (s) comme JSON ou XML. Vous ne pouvez pas directement sérialiser un objet en binaire dans Java et attendre que C# soit capable de le désérialiser. – Fildor

+1

Les deux Java & C# ont un schéma de sérialisation/désérialisation par défaut différent, de sorte que vous devez standardiser le transfert de données avec un composant tiers (JSON, XML ou d'autres formats de texte). Sérialiser dans une langue et désérialiser dans une autre ne donne souvent pas les résultats escomptés. –

+1

Pourquoi n'envoyez-vous pas d'octets au lieu d'encoder Ascii? Vous ne décodez pas les ascii en octets. La méthode send et la méthode receive doivent être symétriques. Tout ce que vous faites pour vous envoyer doit faire dans l'ordre inverse lors de la réception. – jdweng

Répondre

0

Vous avez besoin d'un framework de sérialisation agnostique. Les exemples incluent Google Protocol Buffers, ASN.1, XSD. Fondamentalement, vous devez transformer un fichier de schéma (comme un GPB .proto ou ASN.1 .asn, ou un .xsd) en deux classes POJO et POCO (pour Java et C# respectivement). C'est ce que le compilateur GPB ou un compilateur ASN.1 peut faire pour vous. Ainsi, vous finissez avec des classes dans les deux langues, et ces classes sérialisent/désérialisent vers/à partir d'un format de fil commun.

XSD est légèrement plus complexe; il y a xsd.exe de Microsoft qui va transformer un fichier .XSD en C#. Je n'ai aucune idée s'il y a quelque chose de similaire pour Java.

Je pense que le meilleur endroit pour commencer est avec Google Protocol Buffers - c'est gratuit, et vous permettra de commencer. Et il supporte à la fois JAVA et C#.

Je ne voudrais pas toucher les schémas JSON; les outils de génération de code semblent être loin derrière. Il y a beaucoup de validateurs pour vous dire si un message que vous avez reçu, ou êtes sur le point d'envoyer, est conforme à un schéma JSON, mais cela ne vous aide pas à formuler le message en premier lieu.