【发布时间】:2020-07-31 09:55:53
【问题描述】:
我使用 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();
}
}
【问题讨论】:
-
类似Here 的内容可能对您来说是一个很好的解决方案。使用 BlockingQueue 在线程之间传递信息。
-
@TimHunter BlockingQueue 是否可以与作为单独应用程序运行的每个客户端一起使用?我不确定它如何转移。
-
你给每个客户一个自己的线程让事情变得很困难。如果您没有这种设计,处理这一特定工作的线程可以一次性完成向每个客户端发送的一些工作。
-
@ElliottV4 啊,不。这仅适用于单个程序中的多个线程。对于您的情况,您只需让服务器充当所有客户的“交汇点”。他们告诉服务器他们想说什么,然后服务器将其传递给所有其他客户端。如果您的服务器使用多个线程来处理每个客户端,您只会使用 BlockingQueue。否则,一旦服务器知道该消息,它就可以将其传递给与之连接的其他人。
标签: java multithreading sockets server client