创建一个服务器 让多个终端连接并交互信息 最后用SIGUSR1关闭连接 用SIGUSR2记录连接终端的个数
下面是一个基于 Java 的简单的多线程服务器示例,可以让多个终端连接并交互信息,同时可以通过 SIGUSR1 关闭连接,通过 SIGUSR2 记录连接终端的个数。需要注意的是,由于 SIGUSR1 和 SIGUSR2 是 Unix 信号,在 Windows 上无法测试,需要在 Linux 或 macOS 等 Unix 系统上测试。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
import java.util.Set;
public class MultiThreadServer {
private static final int PORT = 8000;
private static Set<PrintWriter> writers = new HashSet<>();
public static void main(String[] args) {
try {
// 创建 ServerSocket 对象
ServerSocket serverSocket = new ServerSocket(PORT);
// 创建信号处理器
SignalHandler handler = new SignalHandler();
// 注册 SIGUSR1 信号处理器
handler.register(Signal.SIGUSR1, signal -> {
System.out.println("收到 SIGUSR1 信号,关闭连接");
for (PrintWriter writer : writers) {
writer.close();
}
System.exit(0);
});
// 注册 SIGUSR2 信号处理器
handler.register(Signal.SIGUSR2, signal -> {
System.out.println("收到 SIGUSR2 信号,连接终端个数:" + writers.size());
});
// 启动信号处理器线程
Thread signalThread = new Thread(handler);
signalThread.start();
// 循环接收客户端连接
while (true) {
Socket socket = serverSocket.accept();
System.out.println("新客户端连接:" + socket.getInetAddress().getHostName());
// 创建新的线程处理客户端连接
Thread thread = new Thread(new ClientHandler(socket));
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static class ClientHandler implements Runnable {
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
// 获取输入输出流
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
// 将输出流加入集合
writers.add(writer);
// 循环读取客户端消息并广播
String message;
while ((message = reader.readLine()) != null) {
System.out.println("收到消息:" + message);
for (PrintWriter w : writers) {
w.println(message);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭连接并将输出流从集合中移除
try {
socket.close();
writers.remove(socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
在上面的代码中,我们创建了一个 ServerSocket 对象来监听指定端口,然后通过循环接收客户端连接,并为每个连接创建一个新的线程来处理。每个线程包含一个输入流和一个输出流,用于接收和发送消息,并将输出流加入一个集合中,用于广播消息给所有连接的客户端。