从ObjectInputStream读取仅在连接时返回对象

问题描述

| 我有一个基于套接字的简单客户端-服务器应用程序,每个连接都有自己的线程。 当前方案是这样的: Board-是客户端之间共享的对象,已序列化的Plain Old Java对象 ActiveSessions-所有连接都添加到列表中 broadCaster-董事会变更后,将董事会发送给其他客户 问题在于每个线程都连接并修饰了板对象,但是当再次发送该对象时,它会再次发送相同的对象,但是在服务器端该对象的行为正确。
public static void main(String[] args) {
    Board gameBoard = new Board();
    ActiveSessions sessions = new ActiveSessions();
    broadcaster broadcaster = new broadcaster(sessions,gameBoard);

    try {
        ServerSocket socket = new ServerSocket(1234);
        // Timeout after what no more new connections are not accepted.
        socket.setSoTimeout(30 * 1000); 
        logger.info(\"Server started on port \" + socket.getLocalPort());

        while (true) {
            SessionHandler session = new SessionHandler(socket.accept(),gameBoard,broadcaster);
            sessions.addSession(session);
            session.start();
        }

    } catch (SocketTimeoutException e1) {
        logger.info(\"No more new connecions are accpeted,start game or end\");
        gameBoard.setGameState(GameState.PLAYING);
        logger.info(\"Set the gamestate to \" + gameBoard.getGameState());
    } catch (IOException e) {
        logger.info(\"I/O error \" + e.getMessage());
    }
SessionHandler,每个连接都有自己的线程     包服务器;
    import game.Board;
    import game.Turn;

    import java.io.EOFException;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.net.socket;
    import java.net.socketException;
    import java.util.logging.Logger;

    public class SessionHandler extends Thread {

        private Board gameBoard;
        private Socket socket;
        private broadcaster broadcaster;
        private boolean firstConnect = true;

        private ObjectOutputStream out;
        private ObjectInputStream in;
        private static final Logger logger = Logger.getLogger(SocketServer.class.getName());

        public SessionHandler(Socket socket) {
            this.socket = socket; 
        }

        public SessionHandler(Socket accept,Board gameBoard,broadcaster broadcaster) {
            this(accept);
            this.gameBoard = gameBoard;
            this.broadcaster = broadcaster;
        }

        @Override
        public void run() {
            try {
                out = new ObjectOutputStream(socket.getoutputStream());
                in = new ObjectInputStream(socket.getInputStream());

                while (true) {
                    Turn turn = (Turn) in.readobject();
                    if (turn != null) {
                        if (firstConnect) {
                            gameBoard.addplayer(turn.getWhoseTurn());
                            firstConnect = false;
                        }

                        // Add the turn to game board and make validation
                        gameBoard.increaseTurns();
                        broadcaster.send();
                    }
                    System.out.println(\"Turns made \" + gameBoard.getTurns() + \" players \" + gameBoard.getPlayers() + \" dice score \" + turn.getDicescore());
                }
            } catch (EOFException e1) {
                logger.warning(\"Problem reading the object output\");
            } catch (SocketException e) {
                if (\"Connection reset\".equals(e.getMessage())) {
                    System.out.println(\"Client disconnected,performing cleanup\");
                } else {
                    logger.warning(\"Connection between client lost \" + Thread.currentThread());
                }
            } catch (Exception e) {
                e.printstacktrace();
                System.exit(-1);
            }
        }

        public void sendTheGameBoard() {
            try {
                out.writeObject(this.gameBoard);
                out.flush();
            } catch (IOException e) {
                logger.warning(\"Problem with sending game board object \" + e.getMessage());
            }
        }
    }
    class broadcaster {

    private ActiveSessions activeSessions;

    public broadcaster(ActiveSessions aa,Board board) {
        this.activeSessions = aa;
    }

    public void send() {
        // broadcast board forever
            synchronized (activeSessions) {
                Iterator<SessionHandler> active = activeSessions.iterator();

                while (active.hasNext()) {
                    SessionHandler session = active.next();

                    if (!session.isAlive()) {
                        active.remove();
                        session.interrupt();
                    } else { 
                        session.sendTheGameBoard();
                    }
                }
            }

    }
}
    

解决方法

阅读http://java.sun.com/javase/technologies/core/basic/serializationFAQ.jsp#handle。 ObjectOutputStream具有一个缓存,以避免多次发送同一对象。您必须重置流以再次发送副本。