【问题标题】:Netty: Keep Server Socket Open After ctx.flush()Netty:在 ctx.flush() 之后保持服务器套接字打开
【发布时间】:2017-08-04 15:36:17
【问题描述】:

我有两台服务器“A”(由我的朋友构建)和“B”(由我构建,使用 Netty 4.1)。当客户端发送命令时,此服务器“A”和“B”将返回一些响应。我尝试使用简单的 JAVA 客户端套接字连接到该服务器。下面是java客户端代码:

public class SocketClient
{
    public void run()
    {
        try {
            ClassLoader classLoader = getClass().getClassLoader();
            File file = new File(classLoader.getResource("request.txt").getFile());
            String content = new String(Files.readAllBytes(file.toPath()));

            System.out.println("Connecting to server:8888");
            Socket socket = new Socket("myserver.com", 8888);
            DataOutputStream out = new DataOutputStream(socket.getOutputStream());
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            out.write(content.getBytes());
            out.flush();

            while(true) {
                int response = in.read();
                System.out.println(response);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

当客户端连接到服务器 A(非网络)时,read() 方法给我这样的输出:

48
48
57
56
48
50
49
48

但是,当我尝试连接到服务器“B”(使用 netty)时,输出是这样的:

48
48
57
56
48
50
49
48
-1
-1
-1
-1

为什么会这样?顺便说一句,在服务器 B 中,我正在使用 ctx.write() and ctx.flush() 以及如何使服务器 B 获得与服务器 A 相同的行为(不关闭连接,因此它不会返回 -1)

编辑:附加信息

实际上,在服务器“B”中,我使用的是ChannelInboundHandlerAdapterChannelOutboundHandlerAdapter。在做了一些实验之后,问题出在ChannelOutboundHandlerAdapter。当我使用来自InboundAdapterctx.writeAndFlush() 发送响应时,套接字没有关闭。但是当响应被传递到OutboundAdapter 然后我使用ctx.writeAndFlush()OutboundAdapter write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) 方法中发送响应。套接字已关闭

这是我OutboundAdapter的示例:

public class OutboundHandler extends ChannelOutboundHandlerAdapter {

    private static final Logger logger = LogManager.getLogger(OutboundHandler.class);

    //Sending or forwarding message to channel which is already configured
    //condition is depends on which model instance
    //packaging is worked on its packager class
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception
    {
        String response = "Response form OutboundHandler";
        ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));
    } }

谢谢

【问题讨论】:

    标签: java netty


    【解决方案1】:

    在 Netty 服务器实现中,也许您必须更正确地通过 ChannelHandlerContext 处理读/写,例如,而不是使用 ctx.write() ctx.channel().writeandflush() 应该是更正确的方式,也可以关闭使用 ctx.channel().close()ctx.channel().close().sync()可能会有所不同...

    【讨论】:

    • ctx.writeAndFlush()ctx.channel.writeAndFlush() 有什么区别?我的问题是netty总是在writeAndFlush()之后自动关闭连接,所以客户端无法向服务器发送另一条消息。
    • 尽管它们实现相同 ChannelOutboundInvoker 接口的两种方式都应该是相同的,但是对于您的问题,我投资了一些可能有用的网络示例developer.jboss.org/wiki/NettyExampleOfPingPongUsingObject
    • 顺便说一句,我使用的是 netty.io (ver 4.x) 而不是 jboss netty (ver 3.x),我不知道它们是否有显着差异。但是感谢您的建议...哦,我已尝试将 ctx.write(); ctx.flush() 更改为 ctx.channel().writeAndFlush() 但套接字仍会自动关闭。
    • 没有 writeAndFlush 并不能解决您的问题,您的第一个注释代码的逻辑是正确的,它应该像您的情况一样先写入然后刷新......
    【解决方案2】:

    您没有检查流的结束,因此您无休止地回显它。 read() 返回一个。核实。它在流结束时返回 -1。这就是结束。菲尼斯。菲尼托。停在那里。不要打印它。不要继续阅读。不要通过GO。不要收取 200 美元。

    【讨论】:

      【解决方案3】:

      经过一整天的调试,我找到了问题的根本原因。我不小心将ctx.close() 放在了 InboundAdapter 的某个位置,所以当我将消息传递到 OutboundAdapter 并将消息刷新到客户端时,它将关闭连接

      try {
         //some code
      }
      } catch (Exception ex) {
              logger.error(ex);
              ErrorData error = new ErrorData();
              error.setCode("99");
              error.setMessage("General System Error");
      
              //pass the message to OutboundAdapter
              ctx.writeAndFlush(error);
      } finally {
        ctx.close();
      }
      

      所以,我只需要删除ctx.close() 并且服务器停止关闭套接字连接

      【讨论】:

        猜你喜欢
        • 2017-11-11
        • 2015-03-25
        • 2017-09-28
        • 2012-11-23
        • 1970-01-01
        • 2013-04-19
        • 1970-01-01
        • 2011-09-17
        • 1970-01-01
        相关资源
        最近更新 更多