2

ログイン/ログアウトのみが実装されたシンプルなクライアント/サーバー アプリを取得しました。接続を押すと完璧に動作しますが、切断しようとすると問題が発生します(クライアント側でEOFExceptionが発生します)。ストリームの閉鎖が不十分であることが原因であるとほぼ確信しています。ヒントはありますか?

java.io.EOFException
    at java.io.DataInputStream.readByte(DataInputStream.java:98)
    at java.io.ObjectInputStream.nextTC(ObjectInputStream.java:506)
    at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:778)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2006)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1963)
    at com.mtm.ClientConnection.disconnect(ClientConnection.java:54)**

クライアントクラス:

public class ClientConnection implements Admin{

    public ObjectInputStream in;
    public static ObjectOutputStream out;
    public Socket socket;

    public void connect(){

        String host = IP;
        int port = PORTO;

        try {       
            socket = new Socket (host,port);
            out = new ObjectOutputStream(socket.getOutputStream());
            in = new ObjectInputStream(socket.getInputStream());           

            MSG_Login login = new MSG_Login();         
            login.setID(DeviceId.getId().toString());
            send(login);   

            Object c1 = in.readObject();
            if(c1 instanceof MSG_Login){
                Thread thread = new ClientThread(this);
                thread.start();
            }

        }
        catch (UnknownHostException e) {        e.printStackTrace(); }
        catch (SocketException e) {             e.printStackTrace(); }
        catch (IOException e) {                 e.printStackTrace(); }
        catch (ClassNotFoundException e) {      e.printStackTrace(); }
    }

    public void disconnect(){
        try {
            MSG_Logout logout = new MSG_Logout();
            logout.setID(DeviceId.getId().toString());
            send(logout);

            Object c1 = in.readObject();
            if(c1 instanceof MSG_Logout){
                in.close();
                out.close();
                socket.close();
            }
        } 
        catch (IOException e) {  e.printStackTrace(); }
        catch (ClassNotFoundException e) {      e.printStackTrace(); }
    }

    public static void send(Object obj) {
        try {
            out.writeObject(obj);
            out.flush();
            out.reset();
        }
        catch (IOException e) { e.printStackTrace(); }
    }
}

サーバー (スレッド) クラス:

public class Servidor_Thread extends Thread{

    public Socket canal;
    Servidor serv;
    ObjectOutputStream oos=null;
    ObjectInputStream ois=null;
    private boolean logOff;

    public Servidor_Thread(Servidor serv) {
        this.serv = serv;
        canal = serv.socket;
        logOff = false;
    }

     public void run(){
            try {
                ois=new ObjectInputStream(canal.getInputStream());
                oos=new ObjectOutputStream(canal.getOutputStream());
                while(logOff==false){
                    Object obj=ois.readObject();/** Objecto recebido - Reconstrução **/
                    DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                    Date date = new Date();
                    if(obj instanceof MSG_Login){
                        serv.id_database.add(((MSG_Login) obj).getID());
                        serv.getLog().appendConsole("["+dateFormat.format(date)+"]..........User "+((MSG_Login) obj).getID()+" connected.");
                        enviar(obj);
                    }
                    if(obj instanceof MSG_Logout){
                        serv.id_database.remove(((MSG_Logout) obj).getID());
                        serv.getLog().appendConsole("["+dateFormat.format(date)+"]..........User "+((MSG_Logout) obj).getID()+" disconnected.");
                        enviar(obj);
                        stopThread();
                    }
                } 
            }
            catch (IOException e) {                  stopThread();      }
            catch (ClassNotFoundException e) {       e.printStackTrace();   } 
     }

     public void stopThread(){
        logOff = true;
        try {
            ois.close();
            oos.close();
            canal.close();
        } catch (IOException e) {   e.printStackTrace();    }
     }

     public void enviar(Object obj) {
        try {
            oos.writeObject(obj);
            oos.flush();
            oos.reset();
        } 
        catch (IOException e) { e.printStackTrace(); }
     }
}
4

1 に答える 1

3

ここで答えても問題ありません。readObject() メソッドは、ストリームの最後で EOFException をスローします。これは通常の動作です。それをキャッチし、読んでいるストリームを閉じて、読み取りループを終了する必要があります。

于 2013-08-04T00:51:24.900 に答える