【发布时间】:2011-09-02 18:41:39
【问题描述】:
我有简单的基于套接字的客户端-服务器应用程序,每个连接都有自己的线程。 目前的方案是这样的:
- Board - 是在客户端之间共享的对象,序列化的普通旧 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();
}
}
}
}
}
【问题讨论】:
标签: java multithreading sockets