你想擁有一臺服務器一旦服務器發現該端口上的傳入連接,你應該創建一個新的線程來處理該客戶端和服務器之間的通信,而主線程繼續監聽其他傳入的連接。您可以將多個客戶端連接到一臺服務器,如下所示:
private void listen() throws IOException {
serverSocket = new ServerSocket(port)
while (GlobalFlags.listening) {
new ServerThread(serverSocket.accept();
if (GlobalFlags.exit) {
serverSocket.close();
break;
}
}
}
Where Global標誌是控制監聽過程的變量,並非真正必要。你可以做一段時間的真實,並永遠不停地傾聽。
在我的項目中,我有一個主監聽器在線程中運行的服務器控制器。控制器控制GlobalFlags。我敢肯定,不是使用全局標誌,而是進行線程間通信的更好方法,但對我來說這是最簡單的。
ServerThread應該循環所有的時間在發送輸出到客戶端和接收來自客戶端的輸入之間切換。像這樣:
ServerThread(Socket socket) {
super("GameServerThread");
this.socket = socket;
try {
this.socket.setTcpNoDelay(true);
} catch (SocketException e) {
// Error handling
}
this.terminate = false;
}
@Override
public void run() {
try {
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String inputLine, outputLine;
while ((inputLine = in.readLine()) != null) {
outputLine = processInput(inputLine);
out.println(outputLine);
if (terminate) {
break;
}
}
}
out.close();
in.close();
socket.close();
} catch (Exception e) {
// Error handling, should not use Exception but handle all exceptions by themselves.
}
在客戶端,您有一個線程運行通過類似的循環,從服務器接收輸入,然後將輸出發送到服務器。
在此示例中,processInput是用於處理客戶端輸入的函數。如果你想讓服務器發起聯繫,你可以讓服務器在輸出流中發送一些東西,然後再聽取輸入並讓客戶端先聽。
我已經從我自己的一個項目中提取了這個示例,並且this.socket.setTcpNoDelay(true)應該使該過程更快。當http://www.rgagnon.com/javadetails/java-0294.html
「java.net.Socket.setTcpNoDelay()被用於使能/禁用TCP_NODELAY其中禁用/啓用Nagle算法 Nagle算法嘗試通過最小化所發送的段的數量,以節省帶寬:參考這裏。應用程序希望減少網絡延遲並提高性能,他們可以禁用Nagle的算法(即啓用TCP_NODELAY)。數據將以更高的帶寬消耗爲代價提前發送.Nagle的算法在RFC 896中描述。
用java.net.Socket.getTcpNoDelay()獲得當前的「TCP_NODELAY」設置「
因此,要將消息發送到特定的客戶端,您可以將創建時的所有線程置於ArrayList中,以便跟蹤所有當前連接的客戶端。您可以讓processInput方法暫停和輪詢隊列/變量,直到另一個類將消息發送到隊列/變量中。那麼如何獲得類的句柄取決於你的processInput的實現。你可以給每個線程一個ID(這是我在我的項目中做的),也可以讓processInput方法在index = ID處輪詢一個ArrayList。然後發送輸出到客戶端,你將不得不在index = ID處設置變量。
這種方法對我個人而言似乎有點笨重,但我不確定我會怎麼做。您可能會使用隊列並讓processInput將輸入寫入其隊列,然後等待另一個類讀取它並將其響應放入隊列中。但我個人從來沒有在java中使用Queues,所以你應該自己閱讀。
謝謝。我跟着你,直到服務器控制器部分。這是我感到困惑的地方。所以一旦你有這些客戶端通過自己的線程與服務器進行通信,你如何從外部java類獲得一個句柄來向該客戶端發送消息。 因此可以說我有客戶端1在線程XYZ中運行。然後在另一個java類中處理RESTful webservice想要在Thread XYZ上向客戶端1發送消息。它如何獲得該線程的句柄? – Goldcougar 2013-02-19 15:19:44
那麼服務器控制器是非常不相關的問題。所有你真正需要的功能是監聽器是服務器線程和客戶端線程。將消息發送到客戶端的方式將通過您的processInput實現來確定。我個人在另一個類中有一個解碼函數,它與服務器後端的其餘部分進行通信,以根據客戶端的輸入來確定服務器的輸出。我將在您編輯的同時編輯更多信息的帖子。 – 2013-02-19 15:24:23
好吧,我已經添加了一些更多的信息,我會給你一個示例實現,但我自己不太確定什麼是最好的方法。你或許可以考慮一下使用隊列的方法。 – 2013-02-19 15:45:03