2011-04-25 70 views
0

尋找對以下問題的建議。確保客戶端請求的正確響應

我正在使用單個TCP套接字來讀寫消息到服務器的應用程序(客戶端)。

消息是幾種預定義類型之一,它們在抵達時將被解析。

服務器可能隨時廣播消息。

客戶端會向服務器發送消息,並期待響應。然而(這裏是我的問題來了),我不能從套接字讀取收到此消息,因爲我不知道什麼時候可以傳遞。大多數情況下,客戶端響應消息將在客戶端請求後立即傳遞。但是,偶爾會有另一個廣播消息被首先發送。

套接字的讀取通道由單個生產者線程排入阻塞隊列。在一個單獨的消費者線程中,任何消息都會出隊併發送,以供進一步處理。爲了獲得預期的客戶響應,我應該使用事件源/偵聽器語言來讓我的客戶在其(如果)響應到達時得到通知嗎?

感謝您的任何建議。

編輯:我認爲我的問題不清楚,因爲迄今爲止的建議不處理手頭的問題。最後,我確實使用了事件源/偵聽器成語來處理這個問題。再次感謝errort,但我認爲這是封閉的。主持人甚至可能想刪除這個問題。

回答

0

這是使用Java的序列化機制的絕佳機會。你可以這樣做(假設你捕獲所有異常有關,這是爲了簡明扼要省略)

class ClientListeningThread { 

    ObjectInputStream in; 
    ObjectOutputStream out; 

    ClientListeningThread(Socket s) { 
     in = new ObjectInputStream(s.getInputStream()); 
     out = new ObjectOutputStream(s.getOututStream()); 
    } 

    public void run() { 
     while(true) { 
      ClientMessage message = (ClientMessage)in.readObject(); 
      engine.addMessage(this,message); // add to the message queue, signifiying which listening thread to give the response to 
     } 
    } 

    public void send(ServerMessage message) { 
     out.writeObject(message); 
    } 

} 

您的郵件甚至可以在它們回調

類LoginMessage {

public final String username; 
public final String password; 

public LoginMessage(String username, String password) { 
    this.username = username; 
    this.password = password; 
} 

public void callback(ClientListeningThread thread, ServerProcessor engine) { 
    ServerMessage response = engine.attemptLogin(username,password); 
    thread.send(response); 
} 

}

而在你的發動機

while(!requests.isEmpty()) { 
    ClientRequest request = requests.poll(); 
    ClientListeningThread = request.thread; 
    ClientMessage message = request.message; 
    request.callback(thread,this); 
} 
+1

看不到序列化在這裏發揮作用。另請參閱我的編輯。不管怎麼說,還是要謝謝你。 – 2011-04-30 18:06:02

0

您可以使用偵聽器和緩存線程池來實現它。所以你可以創建一個處理消息的Runnable類。然後創建一個監聽器類,它只是實例化一個套接字(或服務器套接字)並創建一個線程池。在監聽器類中創建一個無限循環,用於監聽傳入請求並將socket.accept傳遞到可運行對象的構造函數中,以便它可以處理來自套接字的任何輸入。

代碼會是這個樣子:

public class MessageHandler implements Runnable { 

    String msg = ""; 
    Socket socket = null; 
    BufferedReader in = null; 
    PrintWriter out = null; 

    public void MessageHandler(ServerSocket socket){ 
     this.socket = socket; 
    } 

    @Override 
    public void run(){ 
     //Message read from socket 
     in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     System.out.println("Message: " + in.readLine()); 

     //Reply send back through same socket 
     out = new PrintWriter(socket.getOutputStream(), true); 
     out.println("MESSAGE RECEIVED. THANKS."); 
    } 
} 

你聽類將是這個樣子:

public class SocketListener { 

    ServerSocket socket = null; 
    ExecutorService threadExecutor = null; 
    Runnable runnable = null; 

    public static void main (String[] args){ 
     socket = new ServerSocket(8181); 

     /* Socket will always be listening, when a request arrives a thread will handle 
     * the incoming stream. 
     */ 
     while(true) { 
      threadExecutor = Executors.newCachedThreadPool(); 
      runnable = new MessageHandler(socket.accept); 
      threadExecutor.execute(runnable); 
     } 
    } 
} 

我不知道這是否代碼編譯,但你的服務器的實現可以看起來與此非常相似,並且可以擴展和強大。

您的客戶可以是幾乎相同的,雖然你會使用插槽不是的ServerSocket,也許不同的方式處理消息。

+0

請參閱我的編輯。不管怎麼說,還是要謝謝你。 – 2011-04-30 18:06:46

相關問題