1

TCP ソケットを介したシリアル化されたオブジェクトの送受信に関する問題に直面しています。実際、サーバースレッドとクライアントスレッドの間でオブジェクトを適切に送受信できます。ただし、問題は、受信/送信オブジェクトのプロパティの値を変更した場合、この変更は待機スレッドで実現できませんでした。このコード サンプルを検討してください。

public class ClientThread extends javax.swing.JFrame implements Runnable {

ClientObject mainClient; // Initiliazed after sockets connect to server successfully
.
.
.
      String addNewBuddy = JOptionPane.showInputDialog(this, "Enter the Username of the person who you want to add...");

      mainClient.setBuddyRequest(true);
      mainClient.setBuddyRequestAccount(addNewBuddy);

      send.writeObject(mainClient); // write into an ObjectOutputStream
      send.flush(); // flush it

      System.out.println("mainClient.setBuddyRequest : " + mainClient.isBuddyRequest() + " setBuddyRequestAccount : " + mainClient.getBuddyRequestAccount()); // Check if values changed properly

      ClientObject tempClientObject; // temporary an instance of ClientObject

      while(( tempClientObject = (ClientObject) receive.readObject()) != null){

           if( !tempClientObject.isBuddyRequest() ){

                    JOptionPane.showMessageDialog(this, "Buddy Request Information", "Requested buddy doesnt exist!!!", JOptionPane.ERROR_MESSAGE);
                    break;
                }

                else{
                    JOptionPane.showMessageDialog(this, "Buddy Request Information", "Requested buddy added into your buddy list succesfully", JOptionPane.INFORMATION_MESSAGE);
                    labelSetText = tempClientObject.getNickName();
                    onlineStatus = tempClientObject.isIsOnline();
                    model.addElement(createPanel());
                }

            }
.
.
.
}

したがって、いくつかのプロパティを変更した後、mainClientそれをサーバーに送信します。これは、サーバースレッドがオブジェクトを待って何らかの反応を与える部分です。さらに、クライアントが2番目のオブジェクトを送信すると(カウンターが0より大きくなります)、サーバースレッドはエラーなしでそれを読み取ることができますが、クライアントが変更されたオブジェクトを2番目のメッセージとしてサーバーに送信しても、最初のオブジェクトと2番目のオブジェクトのプロパティに違いはありません! .

        while( ( clientO = (ClientObject) receive.readObject()) != null ){

                counterMessage++;

                 if( counterMessage==1) { // 

                     checkAccountIfExist(toWrite,file.exists(),toModify,clientO); // Check is connected account exist in database of server

                 } // end of if (counter==1)

                 else{ // Second time when server waits 

// prints counter=2 but clientO.isBuddyRequest printed as 'false' 
//instead of 'true' so this makes if statement unreachable!
                     System.out.println("Counter = " + counterMessage + "  BUDDYREQUEST : " + clientO.isBuddyRequest() + " USERNAME : " + clientO.getUserName());

                     if(clientO.isBuddyRequest()){
                         System.out.println("Entered");
                         checkBuddyAvalaible(clientO);
                     }

                 }

        }

最後に、シリアル化可能な ClientObject のコード

public class ClientObject implements Serializable {

    private static final long serialVersionUID = 8662836292460365873L;
    private String userName;
    private String password;
    private String nickName;
    private String message;
    private boolean checkAcc;
    private LinkedList<ClientObject> buddyList;
    private boolean isOnline;
    private boolean buddyRequest;
    private String buddyRequestAccount;

    public ClientObject(String userName, String password){

        this.userName = userName;
        this.password = password;
        this.checkAcc = false;
        this.buddyList = new LinkedList<ClientObject>();
        this.isOnline = false;
        this.buddyRequest = false;
        this.buddyRequestAccount = null;
    }

   ...methods of getters and setters
}

私は問題について明確であったことを願っています.すべての回答に感謝します.とにかくありがとう.

4

2 に答える 2

3

ObjectOutputStream.reset() を呼び出すか、writeUnshared() を使用するだけです。

于 2013-03-27T23:06:19.440 に答える
1

送信コードを書いていると思います:

.....
mainClient = new ClientObject(userName, password);
String clientNickName = JOptionPane.showInputDialog(this, "Enter your NickName");
mainClient.setNickName(clientNickName);
send.writeObject(mainClient);
send.flush();
......

ループで。そうである場合は、Java シリアライゼーションに関する次の事実を読む必要があります。

オブジェクトのシリアル化を実行している間、Java はオブジェクト グラフに似たデータ構造を形成して、シリアル化する必要があるオブジェクトを決定します。シリアル化するメイン オブジェクトから開始し、メイン オブジェクトから到達可能なすべてのオブジェクトを再帰的にトラバースします。シリアル化が必要なオブジェクトごとに、オブジェクトが既にシリアル化されていることを示す識別子を特定の ObjectOutputStream インスタンスに関連付けます。そのため、Java は、ObjectOutputStream にシリアル化されていると既にマークされている同じオブジェクトに遭遇した場合、そのオブジェクトを再度シリアル化するのではなく、同じオブジェクトへのハンドルをシリアル化します。これは、Java が既にシリアライズされたオブジェクトを再シリアライズする必要を回避する方法です。


EDIT EJPのコメント
に基づいて、OPに正しいメッセージを伝えるために投稿を更新しました。 最初に のオブジェクトを via に送信した後、次に変更されたjava のオブジェクトを送信するときに、このタイプのオブジェクトが既にシリアライズされているかどうかを確認します。すでにシリアライズされているため、Java は新しく作成されたものを再度シリアライズしません。それが、反対側で同じオブジェクトを取得している理由です。この問題の解決策は、リセットなど の変更されたオブジェクトを送信するたびに次のようにすることです。
ClientObjectOutputStreamObjectOutputStreamClientObjectobject
ClientObjectObjectOutputStream

send.reset();  

そして、変更されたオブジェクトを反対側に送信します。

于 2013-03-27T19:49:36.273 に答える