📅  最后修改于: 2023-12-03 15:16:32.129000             🧑  作者: Mango
本文介绍了如何使用Java的多线程特性来开发一个多用户聊天室服务器程序的编程方法。这个程序使用了Java的Socket编程API,使得多个客户端可以与服务器建立连接,并在不互相干扰的情况下进行聊天。
下面的代码片段演示了如何使用Java的Socket编程API建立服务器与客户端之间的连接,同时使用Java线程来管理每个连接。
public class ChatServer {
private ServerSocket serverSocket;
private List<ClientThread> clients = new ArrayList<>();
public ChatServer(int port) {
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
System.out.println("Could not create server on port " + port);
System.exit(-1);
}
}
public static void main(String[] args) {
int port = 8888;
if (args.length > 0) {
try {
port = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.out.println("Invalid port number, using default port: " + port);
}
}
ChatServer server = new ChatServer(port);
server.start();
}
public void start() {
System.out.println("Server started on port " + serverSocket.getLocalPort());
while(true) {
try {
Socket socket = serverSocket.accept();
ClientThread clientThread = new ClientThread(clients.size() + 1, socket, this);
clients.add(clientThread);
new Thread(clientThread).start();
} catch (IOException e) {
System.out.println("Error accepting client connection");
}
}
}
public void broadcastMessage(String message, int senderId) {
for (ClientThread thread : clients) {
if (thread.getClientId() != senderId) {
thread.sendMessage(message);
}
}
}
public void removeClient(ClientThread clientThread) {
clients.remove(clientThread);
}
}
class ClientThread implements Runnable {
private int clientId;
private Socket clientSocket;
private ChatServer server;
private BufferedReader reader;
private PrintWriter writer;
public ClientThread(int clientId, Socket clientSocket, ChatServer server) {
this.clientId = clientId;
this.clientSocket = clientSocket;
this.server = server;
try {
reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
writer = new PrintWriter(clientSocket.getOutputStream(), true);
} catch (IOException e) {
System.out.println("Error creating input/output streams for client");
}
}
public void run() {
String inputLine;
try {
while ((inputLine = reader.readLine()) != null) {
System.out.println("Client " + clientId + " says: " + inputLine);
server.broadcastMessage("Client " + clientId + ": " + inputLine, clientId);
}
} catch (IOException e) {
System.out.println("Error reading from client");
} finally {
try {
clientSocket.close();
} catch (IOException e) {
System.out.println("Error closing client socket");
}
server.removeClient(this);
}
}
public void sendMessage(String message) {
writer.println(message);
}
public int getClientId() {
return clientId;
}
}
以上代码片段包含了两个类:ChatServer和ClientThread。ChatServer类包含了服务器的主要逻辑,可以监听并接受客户端连接,并创建一个新的线程(ClientThread)处理每一个连接。ClientThread类表示一个客户端连接的线程。
在ChatServer中,我们首先需要创建一个ServerSocket对象,监听一个指定的端口。一旦有客户端连接,就会调用accept方法,返回一个表示连接的Socket对象。我们接下来就需要为每个连接创建一个ClientThread实例,并将其添加到已连接客户端列表中。然后我们启动一个新的线程来执行这个ClientThread实例。
在ClientThread中,我们使用BufferedReader和PrintWriter对象处理输入和输出。我们在run方法中使用一个while循环来处理客户端输入,如果输入为null就代表客户端已经关闭了连接。如果从输入流中读取到了一行数据,那么我们就将其发送到所有已连接客户端(除了这个发送者)。
当客户端关闭了连接时,就会调用finally块中的代码,包括关闭客户端连接的Socket对象,并从服务器已连接客户端列表中移除该客户端对应的ClientThread实例。
本文介绍了如何使用Java的多线程特性编写一个多用户聊天服务器程序。通过解析上文开头的代码片段,不难看出Java的Socket编程API以及线程API在此中的应用。这个程序还有许多可以改进和优化的部分,例如添加密码验证、保存聊天记录等等。