2012-05-08 35 views
1

我有一個類使用類TCPServer的遊戲。我想分開在TCPServer所有低級別的發送和接收。所以我給TCPServer一個獨立的線程,不斷讀取傳入的消息。我想將這些消息返回到Game。但我不知道如何做到這一點。 Game也應該通過向客戶端發送消息來響應這些消息。如何將消息的發送和接收移動到服務器線程?

我想/知道這是可能的移動線程從TCPServerGame但這是解決這個問題的最好方法嗎?把兩個班級分開是不是更好?

我有以下僞代碼。

public class Game{ 
    TCPServer tcpServer = new TCPServer(); 

    public void execute(){ 
     // do something 
     Object o = new Object; 
     send(o); 

     if(receive(o)){ // WRONG 
      // do something with the receive object 
     } 
    } 

    private void send(Object o){ 
     tcpServer.send(o); 
    } 

    private Object receive(Object o){ 
     return tcpServer.receive(o); 
} 

public class TCPServer extends Thread{ 
    private ServerSocket serverSocket; 
    Socket client = new Socket; 

    public void run(){ 
    Object o = receive(); 
    // How do I get this object o in the Server class in function execute()? 
    } 

    private Object receive(){ 
     return serverSocket.listen(); 

    } 

    public void send(Object o){ 
     client.send(o); 
} 
+0

回答你的問題標題 - 你需要在遊戲邏輯和網絡邏輯之間共享數據容器。基本上,'Queue'的一些子類型。但是由於當前代碼中存在很多缺點,我建議從閱讀有關網絡編程的Java教程開始 - http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html –

+0

,是的,你是對的:將遊戲邏輯與網絡相關的東西分開是一個非常好的主意。 –

回答

2

我認爲正確的做法是使用BlockingQueue s。而不是在當前線程中發送消息,Game只會將它們添加到sendQueueTCPServer然後將有一個接收線程,將添加東西到readQueue和另一個線程,從sendQueue寫入到插座的東西。

我現在不太明白你的線程模型。通常情況下,您有一個ServerSocket調用accept()線程,然後分叉客戶端處理程序線程。如果Game保持着許多這樣的客戶端連接,那麼你就會有這樣的事情:

  1. TCPSERVER有它調用accept()一個線程。
  2. 獲得連接時會創建一個ClientHandler對象,並將其添加到由遊戲處理的客戶端集合中。
  3. 每個ClientHandlersendQueuereceivedQueue - 也許每個都是LinkedBlockingQueue
  4. 每個ClientHandler叉讀線程從客戶端接收後,加入到receivedQueue和正在等待的sendQueue並寫入到客戶端套接字寫線程。

這裏有很多工作要做到這一點。如何在客戶端套接字關閉時正確關閉讀寫器線程將成爲一項挑戰。

希望在這裏有所幫助。

+0

好的爲你的響應。兩個問題。你是否將GameHandler對象的數組保存在Game或TCPServer中?在接收到來自客戶端的消息之後的第二個問題中,消息保存在clientHandler的receivedQueue中。我將如何訪問Game中的這些消息而無需輪詢所有客戶端處理程序以查找新消息? – fibera

+0

@fibera好問題。我假設「遊戲」需要與所有客戶進行交互。它需要訪問客戶端的集合(當然需要以某種方式進行同步),但它可能在TCPServer或Game中。如果TCPServer創建客戶端,那麼它應該管理我猜的列表。 – Gray

+0

對於必須輪詢多個處理程序@fibera而言,可能會有一箇中央讀取隊列,而不是每個客戶端的讀取隊列。但是您需要一個包含ClientHandler和其中讀取對象的包裝對象。該包裝將被添加到中央讀取隊列中。 – Gray

相關問題