繁体   English   中英

Java - 可通过套接字进行序列化和发送对象

[英]Java - serializable and sending object via socket

我收到一个错误:

IOException on socket listen: java.io.NotSerializableException: java.net.Socket

我尝试使用以下代码通过套接字发送对象:

ObjectOutputStream outObjects = new  ObjectOutputStream(socket.getOutputStream());
outObjects.writeObject(currentPlayer);

output.flush();

第二行给出错误....但我已经序列化(实现Serializable)类Player(currentPlayer对象的类)但Player类的成员之一是一个Socket对象.....我尝试重新定义和序列化套接字对象但没有办法解决问题....我在哪里错了?

您无法序列化Socket对象,因此您应该使套接字字段瞬态。 如果您需要某些套接字属性,可以将额外的字段添加到Player以表示这些字段。

这意味着Socket类不可序列化。

您必须将Socket成员设置为瞬态,然后它将不会被序列化。

只需确保在私有readObject(ObjectInputStream)方法中重新创建Socket对象,否则您可能会遇到空指针异常。

编辑回答评论

尝试将套接字成员声明为transient

private transient Socket socket;

这将阻止序列化机器尝试发送socket的值。 请注意,您无法有意义地将包含值(表示操作系统资源,如套接字句柄)的值的对象发送到另一个进程。 在最好的情况下,任何在接收方使用此类对象的尝试都将导致抛出异常。 在最坏的情况下,这种尝试可能会引入细微的错误(数据被发送给错误的用户)。 出于这个原因,这些对象永远不可序列化(除非有人犯了错误)。

请考虑以下(简化)示例:在UNIX上,套接字由整数表示(所谓的文件描述符),在创建套接字时由OS返回。 如果将此值发送到另一个进程,则无法保证该数字实际上是指在接收进程中打开的有效文件句柄。 更糟糕的是,如果在接收过程中存在具有相同数值的文件句柄,则几乎不可能在发送过程中引用相同的套接字打开。 因此,如果在发送数据时该数字实际上在接收过程中用作文件描述符,那么它几乎肯定会在预定目的地之外的任何地方。

如果发送和接收进程在同一台机器上,则有一些方法可以将“套接字”从一个进程转移到另一个进程。 但我怀疑,有一些简单的方法可以从Java访问这些OS调用。

implements Serializable本身并不能使对象可序列化。 对象本身中的任何和所有序列化字段必须依次可序列化(以及它们包含的任何和所有字段)。

由于套接字不可序列化,因此不应尝试通过线路发送它。 您可以通过将其声明为瞬态来将其排除在序列化之外。 然后,反序列化的对象当然没有套接字,因此您可能还需要检查对象中的可选readObject和writeObject方法,这些方法将用于序列化和反序列化。

查看有关序列化的这篇文章

套接字不可序列化,因为它与正在执行的机器,操作系统等相关联。 要可序列化,对象的类必须实现Serializable,并且必须包含所有可序列化的递归对象。

因此,要序列化播放器,必须从序列化中排除其套接字属性。 您可以通过声明属性瞬态来执行此操作:

private transient Socket mySocket;

当播放器被反序列化时,它的套接字将因此为空,并且它很可能无法正常工作。 您应该检查一下您的设计,因为序列化需要套接字工作的对象可能没有意义。

有几种方法可以解决这个问题,最快的方法就是标记你的Socket成员transient 这可确保javas默认序列化将忽略Socket,并且您的副本应包含null。

private transient Socket sock;

或者,您可以提供自己的序列化方法,这要求您自己编写和阅读所有成员。 您可以使用Serializable中定义的方法(参见下文)或实现Externalizable

 private void writeObject(java.io.ObjectOutputStream out)
     throws IOException
 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;

最干净的是将您的玩家状态与您的网络代码分开,从而产生仅具有Seri​​alizable成员的类。 作为奖励,发送类不再包含无效的成员字段。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM