这是我编写的代码,用于通过套接字传输对象 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 通过套接字的交换发生在 2 台 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 和 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
字段应该不使用 transient 关键字。
不确定问题出在哪里,但我想对一些事情发表评论。
- 是否有可能您在不同的 PC 上安装了不同版本的软件?接收方是否肯定在
PM
中有vm
字段? - 最好在每次更改类时增加您的
Serializable
id,以确保PM
类在客户端和服务器上匹配。您还可以删除serialVersionUID
并让 VM 生成一个确保您在两侧都有匹配的类。如果它们不匹配,这将给出一个异常(exception)。 - 您可能知道这一点,但请注意
PM
大小不要超过数据包大小,因为您正在使用DatagramPacket
。它们可以被分割、重新排序、根本不交付等等。我怀疑ObjectInputStream
会给你一个部分对象。 - 确保捕获异常并正确记录相关消息,尽管如果它被抛出,您将不会得到任何对象。
为了后代,建议生成一个 serialVersionUID
而不是依赖 VM 的运行时计算。更改对象时是否更改 ID 取决于您正在实现的分布式系统类型。
顺便说一句,serialVersionUID
是一个类标识符,它帮助 Java VM 验证被序列化的类是否与被反序列化的类的定义相匹配。当对象被反序列化时,VM 会查找对象的类并确保 UID 相同。如果不是,则在反序列化对象时抛出 InvalidClassException
异常。 2 个不同的类是否具有相同的 UID 并不重要。
希望这对您有所帮助。
关于java - 通过可序列化的套接字传输对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7784072/