[英]Java Sockets - How can I send messages to multiple threads?
我使用 Java 制作了一個聊天應用程序(服務器/客戶端)。 注意:服務器作為自己的 jar 文件運行,每個客戶端作為自己的 jar 文件運行。
每個客戶端都在自己的線程上。
每當我向服務器發送消息時,每個客戶端都會收到消息,但是當我從客戶端發送消息時,只有服務器會收到消息。 當客戶端發送消息時,我希望所有連接的客戶端和服務器都能接收消息,這樣所有客戶端都可以一起通信,也可以與服務器通信。
我看過很多關於這個的帖子和視頻,但大多數都太混亂了,我無法理解。 有人可以幫我理解如何在線程之間發送消息嗎? 謝謝!
-- 我的代碼 --
客戶:
public Client(User user, String address, int port) {
try {
socket = new Socket(address, port);
ClientApplicationUI app = new ClientApplicationUI();
app.setTitle("Chat Application - " + user.getUsername());
app.setVisible(true);
ServerConnection connection = new ServerConnection(socket, app);
output = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
new Thread(connection).start();
app.getButton().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (app.getTextField().getText() != null && app.getTextField().getText().length() > 0) {
String message = MessageUtil.getMessage(Message.LOGGER_PREFIX) + " <" + user.getUsername() + "> " + app.getTextField().getText() + "\n";
try {
output.writeUTF(message);
output.flush();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
});
} catch (UnknownHostException e) {
System.out.println(e);
System.out.println("Could not connect! Reason: " + e);
} catch (IOException e) {
System.out.println("Could not connect! Reason: " + e);
}
}
服務器連接
public class ServerConnection implements Runnable {
@SuppressWarnings("unused")
private Socket socket;
private DataInputStream in;
private ClientApplicationUI app;
public ServerConnection(Socket socket, ClientApplicationUI app) throws IOException {
this.socket = socket;
this.app = app;
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
}
@Override
public void run() {
while (true) {
String message;
try {
message = in.readUTF();
app.logMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服務器
public class Server {
private Socket socket = null;
private ServerSocket server = null;
private ExecutorService pool = Executors.newFixedThreadPool(4);
public Server (int port) {
try {
ApplicationUI app = new ApplicationUI();
app.setVisible(true);
server = new ServerSocket(port);
app.logMessage(MessageUtil.getMessage(Message.LOGGER_PREFIX) + " " + MessageUtil.getMessage(Message.INFO) + " Server started!\n");
app.logMessage(MessageUtil.getMessage(Message.LOGGER_PREFIX) + " " + MessageUtil.getMessage(Message.INFO) + " Waiting for new connections...\n");
while (true) {
socket = server.accept();
ConnectionHandler clientThread = new ConnectionHandler(socket, app);
app.logMessage(MessageUtil.getMessage(Message.LOGGER_PREFIX) + " " + MessageUtil.getMessage(Message.INFO) + " A new client has been accepted!\n");
pool.execute(clientThread);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Server server = new Server(58139);
}
}
連接處理程序
public class ConnectionHandler implements Runnable {
private Socket client;
private ApplicationUI app;
private DataInputStream in;
private DataOutputStream out;
public ConnectionHandler(Socket client, ApplicationUI app) throws IOException {
this.client = client;
this.app = app;
in = new DataInputStream(new BufferedInputStream(client.getInputStream()));
out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
}
@Override
public void run() {
try {
app.getButton().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (app.getTextField().getText() != null && app.getTextField().getText().length() > 0) {
String message = MessageUtil.getMessage(Message.LOGGER_PREFIX) + " <Server> " + app.getTextField().getText() + "\n";
try {
sendMessage(message);
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
});
String message = "";
while (!message.equals("/stop")) {
message = in.readUTF();
app.logMessage(message);
}
} catch (IOException e) {
System.err.println("IO exception in connection handler!");
System.err.println(e.getStackTrace());
} finally {
try {
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void sendMessage(String message) throws IOException {
out.writeUTF(message);
out.flush();
}
}
您需要了解 sockets 的工作原理。 它們始終是客戶端和服務器。
有兩種方法可以實現您想要的:
第一個解決方案:
將適用於所有客戶端的消息發送到服務器,並讓服務器將消息分發給所有其他客戶端。 服務器將需要跟蹤已經連接的客戶端,即存儲它們的Socket
。
第二種解決方案:(這完全是不可取的)
如果您想在不涉及實際服務器的情況下向網絡客戶端發送消息,則需要該客戶端充當服務器,或者反過來。 這意味着每個客戶端實際上都需要監聽所有其他客戶端,而不僅僅是服務器。
您絕對應該使用第一個解決方案 go !
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.