2017-09-11 83 views
1

我必须在Java和C#之间进行通信,我需要通过套接字服务器发送对象。这里服务器部分用Java编写,客户端部分用C#编写。我想从服务器(Java)发送一个对象并在客户端(C#)中接收它。但我做不到。将对象从java传输到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; 
    } 
} 

服务器(在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(); 

客户(在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); 

在C#客户端中反序列化字节[]时出现异常。 异常消息是:“输入流不是有效的二进制格式。起始内容(以字节为单位)为:AC-ED-00-05-73-72-00-17-74-65-73-74- 73-6F-63-6B-65 ...“

现在我的问题是,我如何解决这个问题,以反序列化在C#代码并获得从Java服务器发送的对象?

+4

使用像JSON或XML这样的对象的共享中间协议表示形式。您不能直接将对象序列化为Java中的二进制文件,并希望C#能够反序列化它。 – Fildor

+1

Java&C#都有不同的默认序列化/反序列化模式,因此您需要使用第三方组件(JSON,XML或其他文本格式)来标准化数据传输。使用一种语言序列化并在另一种语言中反序列化往往不能提供预期的结果。 –

+1

为什么不发送字节而不是编码到Ascii?您不是将ascii解码回字节。发送方法和接收方法必须是对称的。您收到的所有信息都必须以相反的顺序发送。 – jdweng

回答

0

您需要一个语言不可知的序列化框架。例子包括Google Protocol Buffers,ASN.1,XSD。

基本上,您需要将模式文件(如GPB .proto或ASN.1 .asn或.xsd)转换为POJO和POCO类(分别用于Java和C#)。这就是GPB编译器或ASN.1编译器可以为您做的。因此,你最终会得到两种语言的类,并且这些类会串行化/反串行化到一个通用的连线格式。

XSD稍微复杂一些;有来自Microsoft的xsd.exe会将.XSD文件转换为C#。我不知道Java是否有类似的东西。

我认为最好的开始就是使用Google协议缓冲区 - 它是免费的,并且会帮助您。它支持JAVA和C#。

我不会碰JSON模式;代码生成工具似乎还有很长的路要走。有很多验证器可以告诉您,您收到的消息或即将发送的消息是否符合JSON模式,但这无助于您首先制定消息。