java - 如何在等待响应时不阻塞地实现请求-响应协议(protocol)?

标签 java networking concurrency protocols nonblocking

我需要实现一个使用(双向)请求-响应协议(protocol)同时与多个客户端通信的应用程序。以前我已经为每个客户端使用两个专用线程(一个读取器/ react 器和一个写入器/启动器)实现了这一点。这样做的问题是线程管理变得非常复杂和丑陋。有没有任何标准的方法来处理这个问题,甚至可能只有一个线程,或者至少有一个恒定数量的线程来处理所有客户端?

这是某种通信在具有阻塞实现的线程中的样子:

Command response = request("cmd1", "a", "b");
if(!response.is("OK")) {
    return;
}
response = request("cmd2", "c");
if(!response.is("OK")) {
    return;
}
response = request("cmd3");

在发送请求和等待相应响应之间,我希望当前线程能够执行其他工作,但是一旦响应实际到达就继续执行。

我知道可以使用异步 IO 并注册 Java Future/Runnable 实例以在收到请求响应后运行,但这很容易变成匿名 Runnable 子类的多层嵌套,我怀疑它会比它值得的更痛苦。这可能会导致类似于下面的示例,它很快就会变得高度嵌套且不可读。一定有更简单的方法吗?

request("cmd1", "a", "b", new ResponseHandler() {
    public void response(Command response) {
        if(response.is("OK")) {
            request("cmd2", "c", new ResponseHandler() {
                public void response(Command response) {
                    if(response.is("OK")) {
                        request("cmd3", new NullResponseHandler());
                    }
                }});
        }
    }});

我也考虑过使用专用 Actor framework 的可能性处理请求-响应逻辑。虽然它们看起来可以在这种情况下提供帮助,但我以前从未使用过此类框架,所以我不知道它们是否适合这种情况。

简而言之,我的问题是:如何以非阻塞方式处理任意数量的请求-响应连接,以便恒定数量的线程就足够了? Actor 框架是一种有效的方法吗?

附言。我在这个项目中使用 Java。

最佳答案

我认为使用一些 Java NIO 框架(例如netty .还没有使用过 Actor 框架,所以不知道这是否更合适。

基本上,您创建一个类来处理整个通信并存储必要的信息——框架在后台处理整个线程,您只需提供一个方法,例如messageReceived 并在那里处理。

缺点是,基本上您必须编写自己的状态机,这可能不是那么简单 - 但它肯定是使用 NIO 的最简单方法。

示例:

enum State {
    S0, S1
}
private State state = State.S0;
public void messageReceived(
        ChannelHandlerContext ctx, MessageEvent e) {
    switch(state) {
    case S0:
        // read object from channel and write appropriate response
        e.getChannel().write("HELO");  // writes are asynchronous 
        state = State.S1;
        break;
    case S1:
        // same as S0
        e.getChannel().write("DONE");
        break;
    }
}

请注意,阅读 netty 教程仍然是绝对必要的,因为有些关于 NIO 的东西是无法 self 解释的(至少对我来说不是)。但是有几个易于理解的示例应该可以教给您一些基础知识。

关于java - 如何在等待响应时不阻塞地实现请求-响应协议(protocol)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7859648/

相关文章:

c# - 我如何[我的LAN或至少]全局运行ASP.NET网站

networking - Linux 命名空间 : Is it possible for a network namespace to exist without being associated with a process?

java - EventBus android实现,为什么要反射

java - 如何使用 JSP/Servlets 应用程序在特定时间运行服务?

java - PaintComponent 中的 Object.draw 本身不起作用

ios - iOS 崩溃日志的格式、负载和大小是什么

java - 当集合为空时省略 JAXB 中的包装器标记

c# - 如何重构这些锁?

go - 转到股票行情示例未选择 'done'情况?

concurrency - 想要一个简单的程序来说明使用线程并发 lisp 的使用