消息 Java 关闭多线程套接字服务器
Multi thread socket server shutdown by message Java
我有一个多线程进程来侦听消息并处理它们。如果收到的消息之一是 "shutdown",我希望能够关闭进程。除了关机部分我都实现了。
我有一个 "Multi" class,它使用 start
方法扩展了 java.net.ServerSocket
。里面...
java.net.Socket socket = null;
while (true) {
try {
socket = this.accept();
new Thread(new SocketThread(socket, verifier, threading)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
SocketThread 是 implements Runnable
的另一个 class。有什么方法可以使它工作吗?
我以前不必这样做(因为我通常不会发现自己需要编写太多原始 SocketServer),但是对于这种类型的线程协调,我会尝试类似以下的操作...
public class App {
public static void main(String[] args) {
new App().run();
}
public void run() {
try {
System.out.println("Starting...");
AtomicBoolean running = new AtomicBoolean(true);
Collection<Socket> sockets = new ArrayList<>();
Collection<Thread> threads = new ArrayList<>();
try (ServerSocket socketServer = new ServerSocket(10101)) {
System.out.println("Started.");
while (running.get()) {
Socket socket = socketServer.accept();
sockets.add(socket);
if (running.get()) {
Thread thread = new Thread(new SocketHandler(socket, running));
thread.start();
threads.add(thread);
}
}
System.out.println("Stopping...");
sockets.forEach(socket -> {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
});
threads.forEach(thread -> {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
System.out.println("Stopped.");
} catch (IOException e) {
e.printStackTrace();
}
}
static class SocketHandler implements Runnable {
private final Socket socket;
private final AtomicBoolean running;
SocketHandler(Socket socket, AtomicBoolean running) {
this.socket = socket;
this.running = running;
}
@Override
public void run() {
try {
System.out.println("Client connected.");
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
boolean connected = true;
while (connected){
String command = in.readLine();
System.out.println("Command received: " + command);
if (command == null) {
connected = false;
} else if (command.equals("shutdown")) {
running.set(false);
try (Socket tmpSocket = new Socket("localhost", 10101)) {}
}
// process other commands
}
}
System.out.println("Client disconnected.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
更新:更改了示例以建立与服务器的连接以使其解锁。
更新: 处理客户端断开连接情况的示例代码。感谢 @user207421 强调这一点(谢谢)。
更新: 更改了示例代码以处理多个客户端套接字/线程。请注意,当您关闭套接字时,它将通过一个异常,该异常当前刚刚打印到 stderr。您可能希望以不同的方式处理它。
更新:您可能还会发现模拟多个客户端连接的代码很有帮助:
public class Clients {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> new NormalClient().run());
Thread thread2 = new Thread(() -> new NormalClient().run());
Thread thread3 = new Thread(() -> new NormalClient().run());
Thread thread4 = new Thread(() -> new NormalClient().run());
Thread thread5 = new Thread(() -> new ShutdownClient().run());
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
}
}
class NormalClient {
void run() {
try {
try (Socket socket = new Socket("localhost", 10101);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
for (int i = 0; i < 10; i++) {
out.write("hello " + i);
out.newLine();
out.flush();
sleep(1000);
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
class ShutdownClient {
void run() {
try {
try (Socket socket = new Socket("localhost", 10101);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
sleep(8000);
out.write("shutdown");
out.newLine();
out.flush();
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
我有一个多线程进程来侦听消息并处理它们。如果收到的消息之一是 "shutdown",我希望能够关闭进程。除了关机部分我都实现了。
我有一个 "Multi" class,它使用 start
方法扩展了 java.net.ServerSocket
。里面...
java.net.Socket socket = null;
while (true) {
try {
socket = this.accept();
new Thread(new SocketThread(socket, verifier, threading)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
SocketThread 是 implements Runnable
的另一个 class。有什么方法可以使它工作吗?
我以前不必这样做(因为我通常不会发现自己需要编写太多原始 SocketServer),但是对于这种类型的线程协调,我会尝试类似以下的操作...
public class App {
public static void main(String[] args) {
new App().run();
}
public void run() {
try {
System.out.println("Starting...");
AtomicBoolean running = new AtomicBoolean(true);
Collection<Socket> sockets = new ArrayList<>();
Collection<Thread> threads = new ArrayList<>();
try (ServerSocket socketServer = new ServerSocket(10101)) {
System.out.println("Started.");
while (running.get()) {
Socket socket = socketServer.accept();
sockets.add(socket);
if (running.get()) {
Thread thread = new Thread(new SocketHandler(socket, running));
thread.start();
threads.add(thread);
}
}
System.out.println("Stopping...");
sockets.forEach(socket -> {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
});
threads.forEach(thread -> {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
System.out.println("Stopped.");
} catch (IOException e) {
e.printStackTrace();
}
}
static class SocketHandler implements Runnable {
private final Socket socket;
private final AtomicBoolean running;
SocketHandler(Socket socket, AtomicBoolean running) {
this.socket = socket;
this.running = running;
}
@Override
public void run() {
try {
System.out.println("Client connected.");
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
boolean connected = true;
while (connected){
String command = in.readLine();
System.out.println("Command received: " + command);
if (command == null) {
connected = false;
} else if (command.equals("shutdown")) {
running.set(false);
try (Socket tmpSocket = new Socket("localhost", 10101)) {}
}
// process other commands
}
}
System.out.println("Client disconnected.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
更新:更改了示例以建立与服务器的连接以使其解锁。
更新: 处理客户端断开连接情况的示例代码。感谢 @user207421 强调这一点(谢谢)。
更新: 更改了示例代码以处理多个客户端套接字/线程。请注意,当您关闭套接字时,它将通过一个异常,该异常当前刚刚打印到 stderr。您可能希望以不同的方式处理它。
更新:您可能还会发现模拟多个客户端连接的代码很有帮助:
public class Clients {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> new NormalClient().run());
Thread thread2 = new Thread(() -> new NormalClient().run());
Thread thread3 = new Thread(() -> new NormalClient().run());
Thread thread4 = new Thread(() -> new NormalClient().run());
Thread thread5 = new Thread(() -> new ShutdownClient().run());
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
}
}
class NormalClient {
void run() {
try {
try (Socket socket = new Socket("localhost", 10101);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
for (int i = 0; i < 10; i++) {
out.write("hello " + i);
out.newLine();
out.flush();
sleep(1000);
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
class ShutdownClient {
void run() {
try {
try (Socket socket = new Socket("localhost", 10101);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
sleep(8000);
out.write("shutdown");
out.newLine();
out.flush();
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}