我正嘗試使用java套接字創建客戶端服務器遊戲。我有一個線程服務器來控制遊戲的邏輯。我也有客戶端線程與服務器通信。我使用多個客戶端處理程序線程來促進服務器到客戶端的通信。我使用多個線程使用套接字與其他客戶端線程進行通信。如何促進服務器線程和Java中的多個客戶端線程之間的通信
現在,我有一個如何促進服務器線程和多個客戶端線程之間的通信問題。例如,如果服務器選擇下一個播放器進行播放,那麼它應該如何指示客戶端處理程序線程,並通過套接字與客戶端線程進行通信?
我正嘗試使用java套接字創建客戶端服務器遊戲。我有一個線程服務器來控制遊戲的邏輯。我也有客戶端線程與服務器通信。我使用多個客戶端處理程序線程來促進服務器到客戶端的通信。我使用多個線程使用套接字與其他客戶端線程進行通信。如何促進服務器線程和Java中的多個客戶端線程之間的通信
現在,我有一個如何促進服務器線程和多個客戶端線程之間的通信問題。例如,如果服務器選擇下一個播放器進行播放,那麼它應該如何指示客戶端處理程序線程,並通過套接字與客戶端線程進行通信?
我懷疑你的客戶端線程掛在阻塞讀取操作上。要「釋放」這些線程並使它們發送數據,您必須通過thread.interrupt()來中斷它們。 (這將導致閱讀拋出一個InterruptedException阻塞。)
不過,我已經寫了一些網絡遊戲的自己,我會真的建議你看看到java.nio
packages,尤其是的Selector
類。使用這個類你可以很容易地讓整個服務器成爲單線程的。當涉及到同步所有這些客戶端線程時,這會爲您節省一大筆頭疼的。
我認爲使用像ActiveMQ這樣的現有通信基礎設施將會非常有用,可以處理低層次的管道問題,並且讓您能夠在更高的概念級別解決遊戲設計問題,而不是處理低級錯綜複雜的問題。
這就是說。如果我瞭解你,那麼你有一個遊戲客戶端與多個線程,其中一個處理通信到服務器。在服務器上,每個客戶端和遊戲服務器邏輯都有一個通信線程。
我只會使用套接字進行遠程通信和隊列進行服務器線程之間的通信。在隊列中來回發送不可變對象(或拷貝),所以你不需要同步對消息中數據的訪問。作爲同步的基礎,您可以阻止Socket或BlockingQueue,然後您不需要手動同步,但這需要仔細的協議設計。
我已經按照以下方法完成了此操作。我有一個服務器插槽
public Server(int port, int numPlayers) {
game = new PRGameController(numPlayers);
try {
MessageOutput.info("Opening port on " + port);
ServerSocket clientConnectorSocket = new ServerSocket(port);
MessageOutput.info("Listening for connections");
while (!game.isFull()) {
// block until we get a connection from a client
final Socket client = clientConnectorSocket.accept();
MessageOutput.info("Client connected from " + client.getInetAddress());
Runnable runnable = new Runnable() {
public synchronized void run() {
PRGamePlayer player = new PRGamePlayer(client, game);
}
};
new Thread(runnable).start();
}
} catch (IOException io) {
MessageOutput.error("Server Connection Manager Failed...Shutting Down...", io);
// if the connection manager fails we want to closedown the server
System.exit(0);
}
}
然後在客戶端,我有這樣的事情..
public void connect(String ip) {
try {
comms = new Socket(ip, 12345);
comms.setTcpNoDelay(true);
// get the streams from the socket and wrap them round a ZIP Stream
// then wrap them around a reader and writer, as we are writing strings
this.input = new CompressedInputStream(comms.getInputStream());
this.output = new CompressedOutputStream(comms.getOutputStream());
this.connected = true;
startServerResponseThread();
} catch (IOException e) {
ui.displayMessage("Unable to connect to server, please check and try again");
this.connected = false;
}
if (connected) {
String name = ui.getUserInput("Please choose a player name");
sendXML(XMLUtil.getXML(new NameSetAction(name, Server.VERSION)));
}
}
/**
* This method sets up the server response thread. The thread, sits patiently
* waiting for input from the server, in a seperate thread, so not to hold
* up any client side activities. When data is recieved from the server
* it is processed, to perform the appropriate action.
*/
public void startServerResponseThread() {
// create the runnable that will be used by the serverListenerThread,
// to listen for requests from the server
Runnable runnable = new Runnable() {
public void run() {
try {
// loop forever, or until the server closes the connection
while (true) {
processRequest(input.readCompressedString());
}
} catch (SocketException sx) {
MessageOutput.error("Socket closed, user has shutdown the connection, or network has failed");
} catch (IOException ex) {
MessageOutput.error(ex.getMessage(), ex);
} catch (Exception ex) {
MessageOutput.error(ex.getMessage(), ex);
} finally {
(PRClone.this).connected = false;
// only shutdown the server if the listener thread has not already been
// destroyed, otherwise the server will have already been shutdown
if (serverListenerThread != null) {
// shutdown the thread and inform the application the communications has closed
MessageOutput.debug("Shutting down server listener Thread");
}
}
}
};
// create the thread
serverListenerThread = new Thread(runnable);
// start the thread
serverListenerThread.start();
}
的客戶端能夠通過的OutputStream發送請求到服務器,讀取服務器來自輸入流的數據。
服務器可以接受來自客戶端的請求,並在GameController中處理它,也可以使用outputstream從服務器發送通知,同樣在GameController中。
編輯:另外,我應該注意到,我所有的通信都是通過XML完成的,客戶端或服務器上的控制器解碼XML並執行相關請求。
希望這會有所幫助。它確實爲我做了這項工作,並允許我的多人遊戲運作良好。
我做的事情幾乎完全相同! :-) – Jonathan 2010-10-07 19:14:12