[英]Transferring Object over Sockets-Serializable
这是我编写的用于传输对象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对象上。 在服务器端显示虚拟机详细信息会给我空值。
我的疑问:
编辑-
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?
}
正如@Hovercraft ...提到的那样,如果字段没有标记为transient
,则VM
应该被序列化。 transient
( definition )是Java关键字,表示序列化应该忽略该字段。 如果vm
字段被标记为transient
则它在接收器上始终为null
。 在你的情况下, vm
场不应使用临时关键字。
不确定问题出在哪里,但我认为我会对此发表评论。
PM
具有vm
字段? PM
类在客户端和服务器上匹配时,最好增加您的Serializable
ID。 您还可以删除serialVersionUID
并让VM生成一个确保您在两侧都有匹配的类。 如果它们不匹配,这将给出例外。 DatagramPacket
, PM
大小不会超过数据包大小。 它们可以碎片化,重新排序,根本不交付等。我怀疑ObjectInputStream
是否会为您提供部分对象。 仅供后人使用,建议生成serialVersionUID
而不是依赖VM的运行时计算。 更改对象时是否更改ID取决于要实现的分布式系统类型。
顺便说一下, serialVersionUID
是一个每类标识符,可帮助Java VM验证序列化的类是否与要反序列化的类的定义相匹配。 反序列化对象时,VM查找该对象的类并确保UID相同。 如果不是,则在反序列化对象时会引发InvalidClassException
异常。 如果2个不同的类具有相同的UID则无关紧要。
希望这可以帮助。
数组是Java中的第一类对象,它们不是可序列化的对象。 这个问题有三种基本解决方案:
字段可以声明为瞬态。 可以实现writeObject()/ readObject()方法。 可以声明serialPersistentFields。
希望这会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.