这是我编写的用于传输对象pm(类PM)的代码,该对象包含任何对象vm(类VM)通过套接字。
public class PM implements Serializable{
private static final long serialVersionUID=1L;
VM vm[]=new VM[10];
//IP of the Agent
String IP;
public PM() {
super();
for(int i=0;i<10;i++){
vm[i]=new VM();}
}
}
VM是另一个拥有自己属性的类。
public class VM implements Serializable{
String osType;
}
通过套接字交换对象pm发生在两台PC之间。服务器端执行网络发现后,服务器端从客户端接收对象(因此是类名)。
public class NetworkDiscovery extends TimerTask {
InetAddress controllerIP;
int controllerPort;
static PM pm = new PM();
NetworkDiscovery() throws UnknownHostException {
controllerIP=InetAddress.getLocalHost();
controllerPort=4455;
}
public void run() {
try {
byte[] recvBuf = new byte[5000];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
DatagramSocket dSock = new DatagramSocket(4445);
dSock.receive(packet);
int byteCount = packet.getLength();
ByteArrayInputStream byteStream = new ByteArrayInputStream(recvBuf);
ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(byteStream));
pm=(PM)is.readObject();
System.out.println("object1" +pm.IP);
is.close();
dSock.close();
System.out.println("object" + pm.vm[0].vmName);
} //exceptions are caught etc.
}
}
并在客户端将pm对象发送到服务器:
public class ackDiscovery extends TimerTask{
int agentListenPort;
InetAddress agentIP;
ackDiscovery(Connect c) {
agentListenPort=4445;
c1=c;
}
public void run() {
ObjectOutputStream os = null;
try {
PM pm = new PM();
{
pm.IP = InetAddress.getLocalHost().toString();
pm.vm[i].osType = d1.getOSType();
System.out.println("VMname" +i +pm.vm[i].osType);
pm.vm[i].status = d1.isActive();
}
InetAddress address = InetAddress.getByName("Server_IP");
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(15000);
os = new ObjectOutputStream(new BufferedOutputStream(byteStream));
os.flush();
os.writeObject((PM) pm);
os.flush();
byte[] sendBuf = byteStream.toByteArray();
DatagramPacket packet = new DatagramPacket(sendBuf, sendBuf.length, address, 4445);
int byteCount = packet.getLength();
DatagramSocket dSock = new DatagramSocket();
System.out.println("Quote of the Moment: " + pm.vm[0].osType);
dSock.send(packet);
os.close();
dSock.close();
} //exceptions caught etc.
}
}
所有vm和pm细节都在客户端填充(我已经通过打印来检查它)。在服务器端,转移后只有pm详细信息填充在本地pm对象上。在服务器端显示vm详细信息会给我空值。
我怀疑:
谢谢!
编辑 -
public class VM implements Serializable{
String osType,vmName; //on server's side, these are still null
int UUID,osVersion; // on the server's side, these are 0. Are integer variables initialised to a default of zero?
}
答案 0 :(得分:2)
正如@Hovercraft所提到的那样,是的,VM
也应序列化,如果字段不标记为transient
。 transient
(definition)是Java关键字,表示序列化应忽略该字段。如果vm
字段标记为transient
,那么它将始终作为null
到达接收方。在您的情况下,vm
字段应该不使用transient关键字。
不确定问题是什么,但我认为我会评论一些事情。
vm
中有PM
字段?Serializable
id,以确保PM
类在客户端和服务器上匹配。您也可以删除serialVersionUID
并让VM生成一个确保您在双方都有匹配的类。如果它们不匹配,这将给出例外。PM
大小不超过数据包大小,因为您使用的是DatagramPacket
。它们可能是碎片化的,重新排序的,根本没有交付等等。我怀疑ObjectInputStream
会给你一个部分对象。 仅为后代,建议生成serialVersionUID
而不是依赖VM的运行时计算。更改对象时是否更改ID取决于您要实现的分布式系统类型。
顺便说一句,serialVersionUID
是一个每类标识符,可帮助Java VM验证序列化的类是否与要反序列化的类的定义相匹配。当一个对象被反序列化时,VM会查找该对象的类并确保UID是相同的。如果不是,则在反序列化对象时抛出InvalidClassException
异常。如果2个不同的类具有相同的UID,则无关紧要。
希望这有帮助。
答案 1 :(得分:1)
数组是Java中的第一类对象,它们不是可序列化的对象。这个问题有三种基本解决方案:
可以声明字段是瞬态的。 可以实现writeObject()/ readObject()方法。 可以声明serialPersistentFields。
希望这会有所帮助。