我正在使用 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) 网络库,例如 Netty或Mina来实现这类东西。使用它们需要一些学习,但我认为这是值得的。非阻塞意味着您不会为每个连接指定一个单独的线程,而是当套接字中收到某些内容时您会收到通知。
关于java - 有多个客户端连接到 Java Server,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16751078/