jackson
jackson

Reputation: 21

Netty ChannelRead method

I am a novice in using Netty Framework. I meet a problem, I use Netty to write ServerSocket. The goal of the Server is receiving message from a hardware.The hardware sends a byte everytime. The Server and the hardware have a protocol -- every message starts with '#',and ended by '*'.

@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();
       }

   }     
}

However, a problem occurs. When a hardware first send #abcd, the Server will store #abcd Then the hardware may send efg*.Because of the Netty is asynchronous and event driven, the method ChannelRead() will run from begin to end.So will print efg*,not #abcdefg*

I think a lot. Finally, I have a thought. I use AttribueKey which is like ThreadLocal to binds an array to store all received byte with the channel.Then I get #.....* from the array. But the array very will be very big. It is not a good method. Do you have a better method to solve my problem? Thank you for your help

Upvotes: 0

Views: 404

Answers (1)

PhilStallone
PhilStallone

Reputation: 106

Take a look in the Netty User Guide - Dealing with a Stream-based Transport. The message can become fragmented - so in your case it may receive "#abcd" followed by "efg*". Since you are allocating a CharBuffer each time, the original CharBuffer contains "#abcd". On the second method call, the CharBuffer contains "efg*".

A solution is to use a ByteToMessageDecoder. The decode() will be repeatedly called (by Netty framework) until in ByteBuf is empty (i.e., your decode code empties it). So what you can do in the decode() is keep returning until the "in" ByteBuf contain the * char. Once it does, write the contents of the ByteBuf to the "out" List from the beginning # to the *. Any remaining bytes after the * will be left over in the ByteBuf and the process will continue.

Upvotes: 1

Related Questions