2017-09-11 82 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模式,但這無助於您首先制定消息。