[英]Java TCP Echo Server - Broadcast
我有一個簡單的回顯服務器,我希望當連接的用戶在服務器上鍵入任何內容時,所有其他客戶端和該客戶端都將收到一條消息+“ | MOD”。
它現在不會發送給所有客戶端,但是它應該並且我只是不知道我的代碼出了什么問題,所以現在它將只發送消息+“ | MOD”給發送了消息的客戶端,而不發送給所有其他用戶。這應該。
我只是不明白,我有一個遍歷所有客戶端的循環,但是仍然不會發送給所有人。
服務器:
package com.murplyx.server;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
public static ServerSocket server;
public static ArrayList<Socket> clients = new ArrayList<Socket>();
public static void broadcast(String message) {
try {
for (Socket socket : clients) {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(message);
}
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
try {
server = new ServerSocket(9000);
while (true) {
clients.add(server.accept());
for (Socket socket : clients) {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = in.readLine();
if (line != null) {
broadcast(line + " | MOD");
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
客戶:
package com.murplyx.client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String args[]) {
try {
while (true) {
Socket socket = new Socket("localhost", 9000);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
out.println(input.readLine());
System.out.println(in.readLine());
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
請幫忙。
非常感謝。
您遇到的問題之一是,每個客戶端都會反復read stdin, write socket, read socket, write stdout, ...
無限。
當廣播時,所有其他客戶端通常仍處於read stdin
階段,因此他們不知道套接字上有等待讀取的內容。 他們仍在等待用戶輸入內容。
最簡單的選擇之一是在每個客戶端中啟動兩個線程-一個僅處理read stdin, write socket, ...
,另一個處理read socket, write stdout
。
[另一個(可能更復雜)選項,我們可以使用Java NIO 同時 輪詢兩種插座和標准輸入可用的輸入。
第二個問題是,你堵在accept
服務器的呼叫,然后從每個插座依次閱讀。 您可能會accept
一個線程,並讓每個客戶端僅從該客戶端讀取另一個線程,然后重新廣播到其他線程。 NIO也是一個不錯的選擇-您可以輪詢任何客戶端的讀取。
我不確定ArrayLists如何與套接字一起玩,所以我肯定會回過頭來使用普通的數組(請參閱此處的編輯代碼Java EchoTCPServer-發送給所有客戶端 )
我認為可以解決的一些問題:
在客戶端上:
-停止在While循環中關閉套接字。 在while循環外關閉它(當客戶端用服務器完成時)。 另外,在循環外聲明套接字。
關於此提示 :客戶端建立套接字以連接到服務器時,會自動為它提供設備端口,因此兩個不同的設備永遠不會將相同的IP連接到服務器。 TCP連接由服務器套接字和客戶端套接字兩個端口組成,並且套接字由[deviceip:port,serverip:port](iirc)表示。
-此外,在客戶端上,您無需每次通過while循環時都聲明新的閱讀器。 放在外面。 while循環中唯一的東西應該是您的readline + print語句。
-readLine是一種阻止方法。 (以防萬一,您不知道這意味着什么,這意味着readLine將使程序停留在該位置,直到它實際讀取一行為止。要繞過該行,可以將if語句與.ready()
函數結合使用准備函數檢查是否有任何內容要“讀入”,因此,如果沒有輸入,則不會卡在“ readLine”上。
在服務器上:
-和我之前說的一樣,我將改回使用普通數組。
-您的服務器仍將卡在.accept()上。 這樣,您將永遠無法讀取來自客戶端的輸入,除非在每次連接之后都執行一次。 您可以改用線程監聽,它仍然可以正常工作。
例如:(此代碼與我附加的鏈接(也是您的問題)中的代碼一起,將其放在服務器的while循環之前)
// create a tcp listener thread to deal with listening to clients
Thread listenerThread = new Thread() {
public void run() {
String clientSentence;
while (true) {
//loop through each connected socket
for (int i = 0; i <= intLastSocket; i++) {
Socket z = clientSocket[i];
//make sure the socket is not null or closed (can't do anything
//with closed or null sockets
if ((z != null) && (!z.isClosed())) {
try {
// Deal with TCP input here
BufferedReader input = new BufferedReader(new
InputStreamReader(z.getInputStream()));
// read in a line but only if there is one
if (input.ready()) {
clientSentence = input.readLine();
}
} catch (IOException x) {
printTCP("IOException caught when reading in: "
+ x.toString());
}
if (clientSentence != null) {
System.out.println("Received from client: "
+ clientSentence);
//send this message to the client
outputStream[i].println(clientSentence + " | MOD");
}
// clear the input
clientSentence = null;
}
}
}
}
};
listenerThread.start();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.