【问题标题】:How to make the TCP Server run till it is stopped如何使 TCP 服务器运行直到它停止
【发布时间】:2016-06-09 16:06:11
【问题描述】:

示例https://github.com/spring-projects/spring-integration-samples/tree/master/basic/tcp-client-server 非常适合构建 TCP 服务器应用程序。它很简单并且在 JVM 上运行。它不需要任何应用服务器。

示例使用命令行输入来运行程序。我希望服务器只接受来自 Socket 端口的数据,而不是通过命令行。如果我删除命令行输入,主线程正在完成并且程序不再接受来自端口的输入。我必须让主线程一直运行。

我在想这样的事情:

    boolean isGatewayStopped = false;
    while (!isGatewayStopped) {
        try {
            Thread.sleep(5000);
            isGatewayStopped = getGatewayStatus();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

我有两个问题:

  1. 有没有让主线程继续运行的干净方法?

  2. 如何知道网关已停止?如果用户以“退出”的形式发送 TCP 数据,则可以停止网关。有什么方法可以知道网关停止了吗?

谢谢

【问题讨论】:

    标签: java sockets tcp spring-integration


    【解决方案1】:

    另一种解决方案是这样的:

    public static void main(String[] args) throws Exception {
            ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
            System.out.println("Hit 'Enter' to terminate");
            System.in.read();
            ctx.close();
    }
    

    您启动 ApplicationContext 并等待控制台输入停止。

    编辑

    如果您想通过应用程序中的事件停止程序,您可以注册ApplicationListener并在main存在之前等待屏障:

    CountDownLatch exitLatch = new CountDownLatch(1);
    ctx.addApplicationListener(ContextClosedEvent e -> exitLatch.countDown())
    exitLatch.await();
    

    现在你应该在你的应用程序中想出一些逻辑来在那里调用ctx.stop()

    【讨论】:

    • 我不想从命令行获取输入,因为它是一个服务器。 spring 中是否有任何实用程序可以启动守护线程并轮询网关的状态?
    • 在我的回答中查看编辑。
    • 那是完美的阿尔乔姆。快速提问:参考github.com/spring-projects/spring-integration-samples/tree/… 使用控制通道。 Message operation = MessageBuilder.withPayload("@integrationMBeanExporter.stopActiveComponents(false, 20000)").build(); if (this.exporter != null) { this.controlBusChannel.send(operation);如果我使用控制通道发送 stopActiveComponents(),它会发送 ContextClosedEvent 吗?
    • M-m-m。你真的必须在你的代码中以某种方式调用AplicationContext.close()。是的,您的某些带有@ManagedOperation 的组件可以为此目的从control-bus 调用。
    【解决方案2】:

    您可以从主线程调用网关线程上的 wait() 以使主线程等待直到网关线程完成。您需要从网关线程(何时停止)调用 notify() 以指示它已完成并且等待线程应该继续运行(在这种情况下 main 将运行并退出)。一个例子可以是found here

    或者(对于一个非常简单的应用程序的不同解决方案),您可以尝试以下方法从 main 方法读取数据并在读取的数据等于停止程序的命令时停止程序:

    class Server
    {
       static Executor pool = Executors.newFixedThreadPool(5);
    
       public static void main(String[] args) throws IOException
       {
          ServerSocket serverSocket = new ServerSocket(9000);
          while (true)
          {
             final Socket s = serverSocket.accept();
             Runnable r = new Runnable()
                          {
                             @Override
                             public void run()
                             {
                                // read data from socket 's' here
                                // call System.exit() if command is to stop.
                             }
                          };
             pool.execute(r);
          }
       }
    

    【讨论】:

    • socket 数据的读取由 spring 集成处理,因此无法调用 System.exit()。 Spring 集成已经开放了一个端口来读取数据。我不想为了关闭系统而打开另一个像 9000 这样的端口。
    猜你喜欢
    • 2019-07-21
    • 2017-02-01
    • 2019-11-30
    • 2014-04-15
    • 2015-01-19
    • 1970-01-01
    • 2019-01-04
    • 2013-04-02
    • 1970-01-01
    相关资源
    最近更新 更多