在我的Java套接字程序中,我实现了一个客户端 - 服务器Observer模式。也就是说,服务器主体将其服务器事件发布给已订阅服务器的客户端观察者。这就是理论。
实际上,我无法通过套接字发送客户端观察者来订阅服务器。出现的错误是:“java.io.NotSerializableException:java.net.Socket。”我认为这意味着Java抱怨客户端观察者包含一个Socket,众所周知,它不是Serializable。
但是,Socket是客户端和服务器之间的通信方式!
当客户端似乎包含非Serializable包版广告时,如何实现客户端 - 服务器Observer模式?
以下是一段代码概述,可让您了解正在发生的事情:
服务器
public class Server implements ServerSocketPublisher {
// traditional Observer publisher methods implemented here, such as register,
// deregister, notifySubscribers
// ServerSocket implemented here. Waiting on accept()
}
客户端
public class Client implements ClientSocketSubscriber, Serializable {
// traditional Observer subscriber methods implemented here, i.e. updateClient
Socket connectingSocket = null; //I SUSPECT THIS VARIABLE IS THE PROBLEM
try {
connectingSocket = new Socket();
// set SocketAddress and timeout
connectingSocket.connect(sockAddr, timeout)
if (connectingSocket.isConnected()) {
ObjectOutputStream oos = new ObjectOutputStream
(connectingSocket.getOutputStream());
oos.writeObject(this); // THIS LINE THROWS THE ERROR in STACKTRACES
oos.flush();
oos.close();
}
} catch (/*various exceptions*/) {
}
// close connectingSocket
}
答案 0 :(得分:3)
你有几种方法可以解决这个问题:
将您的套接字标记为瞬态
transient Socket connectionsSocket = null;
而不是实现Serializable实现Externalizable,然后在您的读写对象实现中忽略Socket。
除此之外你还应该阅读
关于瞬态:
关于Externalizable:
答案 1 :(得分:1)
您无法将客户端写入输出流套接字,因为它包含一个Socket。如果您序列化客户端,则序列化其中的所有非瞬态变量,并在您获得异常时进行序列化。
但是,服务器已经有了套接字,所以你不需要发送它和客户端。如果连接发生后所有客户端都是观察者,那么您可以在此时开始等待来自客户端套接字的数据。服务器需要保留一个准备好广播的套接字列表,当它收到要发送的事件时,循环遍历所有套接字并发送注册,注销,notifySubscriber消息
或者,如果您希望将客户端视为服务器端的对象并在其上调用方法(看起来您可能尝试这样做),也许您需要查看RMI - 服务器保存的存根客户端和调用存根将消息发送给客户端。