在Java中,非可序列化套接字是否必须阻止使用客户端 - 服务器Observer模式?

时间:2012-04-28 13:54:09

标签: java sockets serialization client-server

在我的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
}

2 个答案:

答案 0 :(得分:3)

你有几种方法可以解决这个问题:

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

    transient Socket connectionsSocket = null;

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

  3. 除此之外你还应该阅读

    关于瞬态:

    1. Post on SO
    2. 关于Externalizable:

      1. Javabeat

答案 1 :(得分:1)

您无法将客户端写入输出流套接字,因为它包含一个Socket。如果您序列化客户端,则序列化其中的所有非瞬态变量,并在您获得异常时进行序列化。

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

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