2

私のJavaSocketsプログラムでは、クライアントサーバーオブザーバーパターンを実装しました。つまり、サーバーサブジェクトは、サーバーにサブスクライブしているクライアントオブザーバーにサーバーイベントを公開します。それが理論です。

実際には、サーバーにサブスクライブするためにソケットを介してクライアントオブザーバーを送信することはできません。表示されるエラーは、「java.io.NotSerializableException:java.net.Socket」です。これは、Javaが、クライアントオブザーバーに、シリアル化できないソケットが含まれていると不平を言っていることを意味していると思います。

ただし、ソケットはクライアントとサーバー間の通信手段です。

クライアントにシリアル化できない障害物が含まれているように見える場合、クライアントサーバーオブザーバーパターンを実装するにはどうすればよいですか?

何が起こっているのかを理解するためのコードの概要は次のとおりです。

サーバ

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. ソケットを一時的なものとしてマークする

    一時的なソケット接続ソケット = null;

  2. Serializableを実装する代わりに、Externalizableを実装してから、読み取りおよび書き込みオブジェクトの実装でソケットを無視します。

これと一緒にあなたも読むべきです

トランジェントについて:

  1. SOに投稿する

外部化可能について:

  1. ジャバビート
于 2012-04-28T14:02:45.873 に答える
1

Client には Socket が含まれているため、Client を出力ストリーム ソケットに書き込むことはできません。クライアントをシリアル化すると、その中のすべての非一時的な変数がシリアル化され、そのときに例外が発生します。

ただし、サーバー側にはすでにソケットがあるため、ソケットとクライアントを送信する必要はありません。接続が発生した後にすべてのクライアントがオブザーバーである場合、その時点でクライアント側のソケットからのデータを待機し始めることができます。サーバーは、ブロードキャストの準備ができているソケットのリストを保持する必要があります。送信するイベントを取得すると、すべてのソケットをループして、登録、登録解除、notifySubscriber メッセージを送信します。

あるいは、クライアントをサーバー側のオブジェクトとして扱い、その上でメソッドを呼び出したい場合 (これを実行しようとしているように見えます)、サーバーがクライアントのスタブを保持している RMI を調べる必要があるかもしれません。スタブを呼び出すと、メッセージがクライアントに送信されます。

于 2012-04-28T14:07:13.220 に答える