Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

ObjectInputStream.readObject()について

java1.6以上

こんばんは。objectの通信について。
わけがあり、Socket通信で、ObjectInputStream.readObject()についてをつかって、入力口からオブジェクトをリードしたいと思ってます。
じつは、このreadObject()のところでブロックしたいんですが、どうしてもEOFが返ってEOFExceptionをスローします。
まあこれは仕様だと思うので宿命として仕方ないとして、代わりのメソッドとか知ってる方教えてください。
お願いします。

7

回答

10425

閲覧

7件の回答

評価

0

>readObject()のところでブロックしたいんですが、

なにをどうしたいのか、もうちょっと具体的に書いてもらえるかな。
それと、APIDocumentを読む限りでは、
readObject()では、オブジェクトが壊れていない限りは、
EOFExceptionは発生しないように読めるんだが、違うの?

評価

0

//TCPサーバープログラムです

package tcpobjectserver;

import bean.MsgBean;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author 
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            recieve();
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }catch (ClassNotFoundException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public static void recieve() throws IOException, ClassNotFoundException{
           // サーバーソケットの生成
          ServerSocket serverSocket = new ServerSocket(5555);

          System.out.println("クライアントからの接続をポート5555で待ちます");
          // クライアントからの接続を待ちます
          Socket socket = serverSocket.accept();
          System.out.println(socket.getInetAddress() + "から接続を受付ました");

          // 出力ストリームを取得
          //ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
          // 入力ストリームを取得
          ObjectInputStream in = new ObjectInputStream(socket.getInputStream());


          // 読み込んだ行をそのまま出力ストリームに書き出す
          int i = 0;
          long time1 = 0;
          long time2 = 0;
          //while ((inputLine = in.readLine()) != null) {
          for(;;){
                //try{
                    MsgBean msg = (MsgBean)in.readObject();
                    if(i == 0){
                        time1 = System.currentTimeMillis();
                    }
                    System.out.println("msgType " + msg.getType());

                    //out.println(inputLine);
                    i++;
                    if(msg == null){
                        break;
                    }
                //}catch(EOFException e){
                //    e.printStackTrace();
                // }

          }
          time2 = System.currentTimeMillis();
          System.out.println(time2 - time1);
          System.out.println("処理が終了したので接続を切ります");

          // 入出力ストリームを閉じる
          //out.close();
          in.close();
          // ソケットを閉じる
          socket.close();
          // サーバーソケットを閉じる
          serverSocket.close();


    }

}

評価

0

//TCPクライアントです

package tcpobjectclient;

import bean.MsgBean;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author 
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            sendObjMsg();
        } catch (UnknownHostException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InterruptedException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void sendObjMsg() throws UnknownHostException, IOException, InterruptedException{
      // ソケットを生成
      Socket socket = new Socket("localhost", 5555);

      // 出力ストリームを取得
      ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
      // 入力ストリームを取得
     // ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

      int i = 0;
      // 「Hello World」をサーバーに送る
      while(i < 1){
          MsgBean msg = new MsgBean();
          msg.setType("ss");
          out.writeObject(msg);
          i++;
          System.out.print("OK");
          Thread.sleep(1000);
      }
      // 読み込んだデータを表示
      //System.out.println(in.readLine());

      // 入出力ストリームを閉じる
      out.close();
      //in.close();
      // ソケットを閉じる
      socket.close();

    }

}

評価

0


//最後にメッセージオブジェクトです

package bean;

import java.io.Serializable;

/**
 *
 * @author 
 */
public class MsgBean implements Serializable {
    private String type = null;

    public void setType(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }
}

//以上

ご返答ありがとうございます。
この3つのクラスを使って通信を行いたいと思いました。
で、通信する際に毎回コネクトやると大量のデータをやり取りするときに、無駄が多すぎてまずいかなと思い、一度コネクトしたら、あとは同じ入出力を使い続けたいなと思ってます。

Objectの場合、一回目は読み取ってくれるんですが、それ以降EOFExceptionを返してしまいます。

オブジェクトが壊れてるんでしょうか?

何か分かったら、よろしくお願いします。

評価

0

だって、サーバープログラムは、1回通信したら、
接続切るようになってるじゃん。
接続だけじゃなくて、プログラムそのものも終了してんでしょ?

評価

0

おお、大変ありがとうございます!!

今やっとこさ分かりました。

サーバープログラムが終了をしたいと思うのでなく、
Clientプログラムが接続を切ってますね。
1回出力後、out.close()やsocket.close()をしてました。

そうすると、クライアント側のout.close()やsocket.close()の段階で、nullが出力され、サーバーがEOFを検地してEOFExceptionスロー、例外処理後、プログラム終了してたって感じですね。

評価

10

というわけで、次は、
サーバープログラムが通信終了を検知したら、
それを処理後、
再び、通信開始待ちになるようにすればいいです。

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。