2

在我的 Java Sockets 程序中,我实现了客户端-服务器观察者模式。也就是说,服务器主体将其服务器事件发布给已订阅服务器的客户端观察者。这就是理论。

实际上,我无法通过套接字发送客户端观察者来订阅服务器。出现的错误是:“java.io.NotSerializableException:java.net.Socket。” 我认为这意味着 Java 抱怨客户端观察者包含一个 Socket,众所周知,它不是可序列化的。

但是,Socket 是客户端和服务器之间的通信手段!

当客户端似乎包含不可序列化的路障时,如何实现客户端-服务器观察者模式?

这是一个代码概述,可让您了解正在发生的事情:

服务器

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
}
4

2 回答 2

3

您有几种方法可以解决此问题:

  1. 将您的套接字标记为瞬态

    瞬态套接字连接Socket = null;

  2. 而不是实现Serializable实现Externalizable然后在您的读写对象实现中忽略 Socket。

除此之外,您还应该阅读

关于瞬态:

  1. 发布在 SO

关于外部化:

  1. Javabeat
于 2012-04-28T14:02:45.873 回答
1

您不能将客户端写入输出流套接字,因为它包含一个套接字。如果你序列化客户端,你会序列化其中的所有非瞬态变量,这就是你得到异常的时候。

但是,服务器端已经有套接字,因此您不需要发送它和客户端。如果一旦连接发生,所有客户端都是观察者,那么您几乎可以在此时开始等待来自客户端套接字的数据。服务器将需要保留一个准备广播的套接字列表,当它收到要发送的事件时,循环遍历所有套接字并发送注册、注销、通知订阅者消息

或者,如果您希望将客户端视为服务器端的对象并在其上调用方法(看起来您可能正在尝试这样做),也许您需要查看 RMI - 服务器保存客户端的存根和调用存根向客户端发送消息。

于 2012-04-28T14:07:13.220 回答