简体   繁体   English

Java:停止线程TCP服务器的好方法?

[英]Java: nice way to stop threaded TCP server?

I have the following structure for TCP client-server communication: 我有以下TCP客户端 - 服务器通信结构:

  • On server startup server starts acceptor thread, that accepts client connections and passes ServerSocket to it. 在服务器启动服务器上启动接受器线程,它接受客户端连接并将ServerSocket传递给它。
  • When a client connection arrives, acceptor thread calls accept() on ServerSocket and submits client processing job to worker thread (by executor/thread pool) and provides client socket to it. 当客户端连接到达时,接受者线程调用ServerSocket上的accept()并将客户端处理作业提交给工作线程(通过执行器/线程池)并向其提供客户端套接字。
  • Worker in loop reads data from client socket stream, processes it and sends replies. 循环中的Worker从客户端套接字流中读取数据,处理它并发送回复。

The question is how to gracefully stop the whole system? 问题是如何优雅地停止整个系统? I can stop acceptor thread by just closing ServerSocket. 我可以通过关闭ServerSocket来停止接受器线程。 It will cause accept() blocking call to throw SocketException. 它会导致accept()阻塞调用抛出SocketException。 But how to stop workers? 但是如何阻止工人呢? They read from stream and this call is blocking. 他们从流中读取并且此调用正在阻止。 According to this streams does not throw InterruptedException and thus worker cannot be interrupt()'ed. 根据这个流不会抛出InterruptedException,因此worker不能被中断()。

It looks like I need to close worker socket from another thread, right? 看起来我需要从另一个线程关闭工作套接字,对吗? For this, socket should be made a public field or a method should be provided in worker to close it. 为此,套接字应该是一个公共字段,或者应该在worker中提供一个方法来关闭它。 Will this be nice? 这会不错? Or may be my whole design is flawed? 或者可能是我的整个设计有缺陷?

Your model works appropriately. 你的模型运作正常。 The best way of interrupting non-interruptable constructs like IO is to close the socket. 中断IO等不可中断构造的最佳方法是关闭套接字。 You can of course handle it before you go into a blocking state, but if the IO functions don't react to interruption you dont really have many good options 你当然可以在进入阻塞状态之前处理它,但是如果IO功能没有对中断做出反应你就没有很多好的选择

I would suggest using a boolean flag that the workers check periodically. 我建议使用工作人员定期检查的布尔标志。 Call the flag shouldStop and if it's set to true, the worker cleans up and then dies. 调用标志shouldStop ,如果设置为true,则工作人员清理然后死亡。 Following this method would allow you to implement some clean-up code so you don't leave resources hanging, etc. 遵循此方法将允许您实现一些清理代码,以便您不会遗留资源等。

You must not simply stop the server. 您不能简单地停止服务器。 The shutdown process might take a while while cleanup occurs because you need to ensure consistency. 关闭过程可能需要一段时间才能进行清理,因为您需要确保一致性。

Imagine a database server, if you simply shut it down while it is carrying out transactions you may leave its data inconsistent. 想象一下一个数据库服务器,如果你只是在执行事务时关闭它,你可能会让它的数据不一致。 That's why it typically takes a while to shutdown the server. 这就是关闭服务器通常需要一段时间的原因。

  • You must first stop accepting new connections in the server. 您必须先停止接受服务器中的新连接。
  • Then you can either wait for the current worker threads to finish their work and then close the server and shutdown officially. 然后,您可以等待当前工作线程完成其工作,然后关闭服务器并正式关闭。
  • Or you force the worker threads to close their connections with the 或者您强制工作线程关闭它们的连接
    client (probably using some sort 客户端(可能使用某种方式
    of flag as suggested). 建议的旗帜)。 This might imply some cleanup to leave data consistent, for instance revert trasnsactions or any kind of changes you have done in files or in memory. 这可能意味着需要进行一些清理以使数据保持一致,例如还原trasnsactions或您在文件或内存中进行的任何类型的更改。

Closing the connections with the clients in the server side should cause the clients to get a EOF on their sides as far as I understand. 根据我的理解,关闭与服务器端客户端的连接应该会导致客户端在其侧面获得EOF。

[EDIT-1] [EDIT-1]

I have delved a bit on the issue, just because I had not used sockets in a while and because I found the question interesting. 我在这个问题上钻了一点,只是因为我有一段时间没有使用套接字,因为我觉得这个问题很有意思。 I think as it has been well pointed out by others, the only option is to close the socket, which according got Javadocs will automatically close the input and output streams/ 我认为,正如其他人已经明确指出的那样,唯一的选择是关闭套接字,根据Javadocs会自动关闭输入和输出流/

If there are chances that the thread is not IO-blocked, but in wait state or sleeping, I think it is still recommended to issue a Thread.interrupt() for the corresponding worker thread of a given socket; 如果线程没有被IO阻塞,但处于等待状态或休眠状态,我认为仍然建议为给定套接字的相应工作线程发出Thread.interrupt(); because there cannot be certainty of the blocking of state of every thread. 因为不可能确定每个线程的状态被阻塞。

public static class IOServerWorker implements Runnable{

        private Socket socket;

        public IOServerWorker(Socket socket){
            this.socket = socket;
        }

        @Override
        public void run() {
            String line = null;
            try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                while( (line = reader.readLine())!=null){
                    System.out.println(line);
                }
                reader.close();
            }catch(IOException e){
                //TODO: do cleanup here
                //TODO: log | wrap | rethrow exception
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM