我必须在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#客户端反序列化byte []期间出现异常。 异常消息是:“输入流不是有效的二进制格式。起始内容(以字节为单位)为:AC-ED-00-05-73-72-00-17-74-65-73-74-73 -6F-63-6B-65 ......“
现在我的问题是,如何解决问题以便在C#代码中反序列化并从Java中获取从服务器发送的对象?
答案 0 :(得分: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 Protocol Buffers - 它是免费的,并且会让你前进。它支持JAVA和C#。
我不会触及JSON模式;代码生成工具似乎远远落后。有很多验证器可以告诉您,您收到或即将发送的消息是否符合JSON模式,但这并不能帮助您首先制定消息。