我正在使用Java创建一个简单的套接字服务器。我能够一次连接一个客户端,我试图实现Threads来处理多个客户端。在我的Server构造函数中,我创建了一个处理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();
}
}
}
}
答案 0 :(得分:2)
你正在ClientThread
构造函数中进行连接。因此,new ClientThread(...)
永远不会返回,直到您发送TERMINATE
命令。将逻辑放在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来实现这类内容。有一些学习要使用它们,但我认为它值得。非阻塞意味着您没有为每个连接专用一个单独的线程,而是在套接字中收到某些内容时通知您。
答案 1 :(得分:0)
您没有为run
Class提供Thread
方法的实现。
将ClientThread的处理逻辑放在run
方法
为了使您的代码模块化并且更易于管理,请将您的ClientThread
类公开,并在这些线程之间仅共享必要的资源。
public class ClientThread extends Thread { //make class public
private Socket socket;
// define all other references
ObjectOutputStream output = null;
//...
public ClientThread(Socket socket) throws IOException {
this.socket = socket;
}
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 {
message = (String) input.readObject();
displayMessage("\n" + message);
} while (!message.endsWith(">>> TERMINATE"));
} catch (ClassNotFoundException classNotFoundException) {
displayMessage("\nUnknown object type recieved");
} finally {
closeConnection();
}
}
}}