![](/img/trans.png)
[英]NotSerializableException when sending an serializable object over socket?
[英]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;
最干净的是将您的玩家状态与您的网络代码分开,从而产生仅具有Serializable成员的类。 作为奖励,发送类不再包含无效的成员字段。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.