java - 如何在服务器/客户端(JFrame)中使用线程?
问题描述
我想从我的代码中发送/接收String
来自多个客户端的消息(对象)。
这是没有尝试使用线程的代码(它从服务器/客户端发送/接收消息)
ServerGui
package server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerGui extends javax.swing.JFrame {
static ServerSocket serverSocket;
static Socket clientSocket;
static DataInputStream inputFromClient;
static DataOutputStream outPutToClient;
/** Creates new form ServerGui */
public ServerGui() {
initComponents();
}
private void sendActionPerformed(java.awt.event.ActionEvent evt) {
try{
String sendMsg = "";
sendMsg = msgText.getText().trim();
outPutToClient.writeUTF(sendMsg);
msgText.setText("");
} catch (Exception e) {}
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ServerGui().setVisible(true);
}
});
String msg = "";
try {
serverSocket = new ServerSocket(2021);
clientSocket = serverSocket.accept();
inputFromClient = new DataInputStream(clientSocket.getInputStream());
outPutToClient = new DataOutputStream(clientSocket.getOutputStream());
while (!msg.equalsIgnoreCase("quit")){
msg = inputFromClient.readUTF();
chatArea.setText(chatArea.getText().trim() + "\nClient: " + msg);
}
} catch (Exception e) {}
}
// Variables declaration - do not modify
private static javax.swing.JTextArea chatArea;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextField msgText;
private javax.swing.JButton send;
// End of variables declaration
}
Client
package client;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
public class ClientGui extends javax.swing.JFrame {
static Socket clientSocket;
static DataOutputStream outputToServer;
static DataInputStream inputFromServer;
public ClientGui() {
initComponents();
}
private void sendActionPerformed(java.awt.event.ActionEvent evt) {
try{
String sendMsg = "";
sendMsg = msgText.getText().trim();
outputToServer.writeUTF(sendMsg);
msgText.setText("");
} catch (Exception e) {}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ClientGui().setVisible(true);
}
});
try {
clientSocket = new Socket("127.8.8.1", 2021);
inputFromServer = new DataInputStream(clientSocket.getInputStream());
outputToServer = new DataOutputStream(clientSocket.getOutputStream());
String msg = "";
while (!"quit".equalsIgnoreCase(msg)){
msg = inputFromServer.readUTF();
chatArea.setText(chatArea.getText().trim() + "\nServer: " + msg);
}
} catch (Exception e) {}
}
// Variables declaration - do not modify
private static javax.swing.JTextArea chatArea;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextField msgText;
private javax.swing.JButton send;
// End of variables declaration
}
这是在我尝试使用线程之后(消息仅从一个客户端发送到服务器,反之亦然)。
serverGui1
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ServerGui1().setVisible(true);
start();
}
});
}
public static void start() {
new Thread(new ServerHandler()).start();
}
private static class ServerHandler implements Runnable {
@Override
public void run() {
try {
serverSocket = new ServerSocket(2021);
new Thread(new ClientHandler(serverSocket.accept())).start();
} catch (Exception e) {
}
}
}
private static class ClientHandler implements Runnable {
private Socket clientSocket;
private String msg = "";
public ClientHandler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
@Override
public void run() {
try {
inputFromClient = new DataInputStream(clientSocket.getInputStream());
outPutToClient = new DataOutputStream(clientSocket.getOutputStream());
while (!msg.equalsIgnoreCase("quit")) {
msg = inputFromClient.readUTF();
chatArea.setText(chatArea.getText().trim() + "\nClient: " + msg);
}
} catch (Exception e) {
}
}
}
cleintGui1
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ClientGui1().setVisible(true);
start();
}
});
}
public static void start() {
try {
clientSocket = new Socket("127.8.8.1", 2021);
outputToServer = new DataOutputStream(clientSocket.getOutputStream());
new Thread(new Listener()).start();
} catch (Exception e) {}
}
private static class Listener implements Runnable {
@Override
public void run() {
try {
inputFromServer = new DataInputStream(clientSocket.getInputStream());
String msg = "";
while (!"quit".equalsIgnoreCase(msg)){
msg = inputFromServer.readUTF();
chatArea.setText(chatArea.getText().trim() + "\nServer: " + msg);
}
} catch (IOException e) {} //Exception e
}
}
那么,如何修复我的代码?
解决方案
在这种情况下,你有一个错误,你只会得到一个客户
String msg = "";
try {
serverSocket = new ServerSocket(2021);
clientSocket = serverSocket.accept();
inputFromClient = new DataInputStream(clientSocket.getInputStream());
outPutToClient = new DataOutputStream(clientSocket.getOutputStream());
while (!msg.equalsIgnoreCase("quit")){
msg = inputFromClient.readUTF();
chatArea.setText(chatArea.getText().trim() + "\nClient: " + msg);
}
} catch (Exception e) {}
因为serverSocket.accept();
在循环之外。要修复您的代码,您应该更改此部分
boolean EOF = true
try {
serverSocket = new ServerSocket(2021);
while (EOF){
clientSocket = serverSocket.accept(); // main thread sleeps until new client is connected, if this stops UI thread then you will have to make one thread for it
new Thread(new Runnable(){
run(){
inputFromClient = new DataInputStream(clientSocket.getInputStream());
outPutToClient = new DataOutputStream(clientSocket.getOutputStream());
....
}
}).start()
}
} catch (Exception e) {}
在我的情况下,为每个客户创建新线程并不是那么好
但您可以使用 FixedThreadPool 执行器对其进行更新
FixedThreadPool vs CachedThreadPool:两害相权取其轻
抱歉,我没有使用编辑器,它可能包含我发布的语法问题,因为您了解如何工作
推荐阅读
- python - 为什么我在连接到远程服务器时收到“getaddrinfo failed”?
- python - 基于 Python 的 exe 在 CMD 处抛出错误(pynput 模块)
- javascript - CSS Onclick 关闭(不显示) 不工作,响应式设计
- c# - 带有模板命令绑定的自定义 ListboxItem
- java - Gradle 无法将 sysout 写入文件 - java.io.IOException:无法删除文件
- c# - 如果我只更改一个,为什么所有列表(在列表中)的值都会改变?
- c++ - 为什么下面的代码打印“AA”而不是“A”?
- python - 为什么 Python 内置数字类型和十进制模块在同一操作上有所不同?
- .net - F# 编译器插件,如 haskell 或
- excel - 通过 VBA 从 Excel 中的主范围中查找范围子集组合