Netty 网状通道读取法

Netty 网状通道读取法,netty,serversocket,channel,Netty,Serversocket,Channel,我是使用Netty框架的新手。我遇到一个问题,我用Netty来写ServerSocket。 服务器的目标是接收来自硬件的消息。硬件每次发送一个字节。服务器和硬件有一个协议——每条消息都以“#”开头,以“*”结尾 @Sharable class ServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object m

我是使用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();
       }

   }     
}
但是,出现了一个问题。当硬件首次发送时,服务器将存储 然后,硬件可能会发送
efg*
。由于网络是异步和事件驱动的,因此方法
ChannelRead()
将自始至终运行。因此打印
efg*
,而不是
#abcdefg*

我想了很多。最后,我有一个想法。我使用
AttribueKey
,它类似于
ThreadLocal
,绑定一个数组来存储通道中所有接收到的字节。然后我从数组中获取
#…*
。但是阵列将非常大。这不是一个好方法。
你有更好的方法解决我的问题吗?感谢您的帮助

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


解决方案是使用ByteToMessageDecoder。decode()将被(Netty framework)反复调用,直到in ByteBuf为空(即,您的解码代码将其清空)。因此,在decode()中可以执行的操作是不断返回,直到“in”ByteBuf包含*char。完成后,将ByteBuf的内容从开始处#到*写入“输出”列表。*之后的所有剩余字节都将保留在ByteBuf中,该过程将继续。

这对我非常有帮助。我使用你的方法。但是解码器不能是
@sharable
,所以当有很多客户端时,我如何使用服务器?服务器为每个客户端连接创建一个通道。您需要为每个通道创建一个新的处理程序实例(或多个实例),否则同一个处理程序将用于多个线程,在这种情况下,处理程序需要是线程安全的-这需要同步和@Shareable(如果由于开销和增加的复杂性以及潜在的锁争用问题可以避免,则不建议使用).谢谢你的帮助!现在,我知道内蒂·莫雷特了,如果你觉得这个问题已经被回答了,你介意把它标记为已回答吗?