gpt4 book ai didi

java - 有多个客户端连接到 Java Server

转载 作者:行者123 更新时间:2023-12-02 07:00:13 26 4
gpt4 key购买 nike

我正在使用 Java 创建一个简单的套接字服务器。我能够一次连接一个客户端,我尝试实现线程来处理多个客户端。在我的服务器构造函数中,我创建了一个处理 ServerSocket 的线程,并且应该继续监听新客户端。连接套接字后,我尝试创建另一个线程来处理客户端套接字。但我仍然无法连接多个客户端。我尝试连接的第二个客户端将无法获取 IO 流。

public class Server extends JFrame {

private JTextField enterField;
private JTextArea displayArea;
private ObjectOutputStream output;
private ObjectInputStream input;

private ServerSocket server;
private Socket connection;
private int counter = 1;

public Server() {
super("Server");
enterField = new JTextField();
enterField.setEditable(false);
enterField.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent event) {
sendData(event.getActionCommand());
enterField.setText("");

}
});

add(enterField, BorderLayout.NORTH);
displayArea = new JTextArea();
add(new JScrollPane(displayArea));
setSize(300, 150);
setLocation(500, 500);
setVisible(true);

new Thread(new Runnable() {
public void run() {
try {
server = new ServerSocket(50499, 100);
displayMessage("Listening on Port: "
+ server.getLocalPort() + "\n");
for (;;) {
Socket nextClient = server.accept();
displayMessage("Client Connected");
new ClientThread(nextClient).start();
nextClient = null;
}
} catch (IOException exception) {
exception.printStackTrace();
}
}
}).start();
}

private void closeConnection() {
displayMessage("\nTerminating connection\n");
setTextFieldEditable(false);
try {
output.close();
input.close();
connection.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}

private void displayMessage(final String string) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
displayArea.append(string);
}
});
}

private void setTextFieldEditable(final boolean editable) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
enterField.setEditable(editable);

}

});

}

private void sendData(String message) {
try {
output.writeObject("SERVER>>> " + message);
output.flush();
displayMessage("\nSERVER>>> " + message);
} catch (IOException ioException) {
displayArea.append("\nError Writing Object");
}
}

private class ClientThread extends Thread {

public ClientThread(Socket socket) throws IOException {
try {
connection = socket;
output = new ObjectOutputStream(socket.getOutputStream());
output.flush();
input = new ObjectInputStream(socket.getInputStream());
displayMessage("Got I/O Stream\n");
displayMessage("Connection " + counter + " received from: "
+
connection.getInetAddress().getHostName());
counter++;
String message = "Connection Sucessful";
sendData(message);
setTextFieldEditable(true);
do {

message = (String) input.readObject();
displayMessage("\n" + message);
} while (!message.endsWith(">>> TERMINATE"));

} catch (ClassNotFoundException classNotFoundException) {
displayMessage("\nUnknown object type recieved");

} finally {
closeConnection();
}

}
}
}

最佳答案

您正在 ClientThread 构造函数内执行连接操作。因此,在您发送 TERMINATE 命令之前,new ClientThread(...) 永远不会返回。将逻辑放入 run() 方法中。

private class ClientThread extends Thread {
private Socket socket;

// The queue, thread-safe for good measure
private Queue<String> queue = new ConcurrentLinkedQueue<String>();

public ClientThread(Socket socket) throws IOException {
this.socket = socket;
}

public void send(String message) {
if (message != null) {
this.sendQueue.add(message);
}
}

public void run() {
try {
connection = socket;
output = new ObjectOutputStream(socket.getOutputStream());
output.flush();
input = new ObjectInputStream(socket.getInputStream());
displayMessage("Got I/O Stream\n");
displayMessage("Connection " + counter + " received from: "
+ connection.getInetAddress().getHostName());
counter++;
String message = "Connection Sucessful";
sendData(message);
setTextFieldEditable(true);
do {
// Purge the queue and send all messages.
while ((String msg = queue.poll()) != null) {
sendData(msg);
}
message = (String) input.readObject();
displayMessage("\n" + message);
} while (!message.endsWith(">>> TERMINATE"));
} catch (ClassNotFoundException classNotFoundException) {
displayMessage("\nUnknown object type recieved");
} finally {
closeConnection();
}
}
}

通常,您将从其他线程向连接发送消息:

ClientThread client = new ClientThread(newClient);
client.start();
client.send("Hi there");

就我个人而言,我会使用非阻塞 (NIO) 网络库,例如 NettyMina来实现这类东西。使用它们需要一些学习,但我认为这是值得的。非阻塞意味着您不会为每个连接指定一个单独的线程,而是当套接字中收到某些内容时您会收到通知。

关于java - 有多个客户端连接到 Java Server,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16751078/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com