Netty ChannelRead 方法

Posted

技术标签:

【中文标题】Netty ChannelRead 方法【英文标题】:Netty ChannelRead method 【发布时间】:2014-12-20 07:58:08 【问题描述】:

我是使用 Netty 框架的新手。遇到一个问题,我用Netty写ServerSocket。 服务器的目标是从硬件接收消息。硬件每次发送一个字节。服务器和硬件有一个协议——每条消息都以“#”开头,以“*”结尾。

@Sharable
class ServerHandler extends ChannelInboundHandlerAdapter 
   @Override
   public void channelRead(ChannelHandlerContext ctx, Object msg) 
       BytBuf in = (ByteBuf) msg;
       CharBuffer charBuffer = CharBuffer.allocate(100);
       String recedata ;
       byte tmp;
       try 
           while (in.isReadable()) 
             tmp = in.readByte();
             if (tmp != 42)     
                charBuffer.append((char) tmp);
               // System.out.println(String.valueOf(charBuffer.array()));
              else               //means receive a byte '*'
                charBuffer.append('*');
                count = 0; 
                recData = String.valueOf(charBuffer.array());
                logger.debug("receive message is " + recData);
              
       catch(Exception e)
             e.printStackTrace();
       

        

但是,出现了问题。当硬件第一次发送#abcd时,服务器将存储#abcd 然后硬件可能会发送efg*。由于Netty是异步的和事件驱动的,方法ChannelRead()会从头到尾运行。所以会打印efg*,而不是#abcdefg*

我想了很多。最后,我有一个想法。我使用AttribueKey 就像ThreadLocal 绑定一个数组以存储所有接收到的字节与通道。然后我从数组中得到#.....*。但数组会很大。这不是一个好方法。 你有更好的方法来解决我的问题吗?谢谢你的帮助

【问题讨论】:

【参考方案1】:

查看 Netty 用户指南 - 处理基于流的传输。消息可能会变得支离破碎 - 因此在您的情况下,它可能会收到“#abcd”后跟“efg*”。由于您每次都分配一个 CharBuffer,因此原始 CharBuffer 包含“#abcd”。在第二个方法调用中,CharBuffer 包含“efg*”。

解决方案是使用 ByteToMessageDecoder。 decode() 将被重复调用(由 Netty 框架),直到 ByteBuf 为空(即,您的解码代码清空它)。因此,您可以在 decode() 中执行的操作是不断返回,直到“in”ByteBuf 包含 * 字符。完成后,将 ByteBuf 的内容写入“out”列表,从开头的 # 到 *. * 之后的任何剩余字节都将留在 ByteBuf 中,并且该过程将继续。

【讨论】:

这对我很有帮助。我用你的方法,但是解码器不能是@sharable,那么在客户端很多的情况下如何使用服务器 服务器为每个客户端连接创建一个通道。您需要为每个通道创建一个新的处理程序实例(或多个实例),否则同一处理程序将用于多个线程,在这种情况下,处理程序需要是线程安全的 - 这需要同步和 @Shareable(如果可以避免,则不推荐)开销和增加的复杂性和潜在的锁争用问题)。 感谢您的帮助!现在,我更了解 Netty 太好了,如果您认为已回答,介意将问题标记为已回答吗?

以上是关于Netty ChannelRead 方法的主要内容,如果未能解决你的问题,请参考以下文章

Netty channelRead 从未调用过

Netty中为啥执行channelReadComplete但是不执行channelRead

Netty中的channelRead和messageReceived的区别

案例分享Netty线程安全疑问

channelRead对于耗时业务逻辑处理的优化

Netty之非阻塞处理