How to retrieve a String when there is a continuous flow of the messages at the server from a buffer?

淺唱寂寞╮ 提交于 2019-12-24 22:41:37

问题


I implemented a basic Client and Server program using Netty. Client sends group of message strings to the server and the server accepts and displays it to the terminal. I can do this for any number of strings. But sometimes the strings are cut to half or any size and are displayed at the server. Is there any way to eliminate this? We are sending QuickFix Strings from Client.

Below is my sample QuickFix string:

8=FIX.4.29=0007935=A49=TTDS68AO56=RaviEx34=152=20170427-14:05:04.572108=60141=Y98=010=242

The character "r" in the above string is an SOH character. Now my requirement is: When I send multiple strings in a loop from ClientHandler to the Server,some strings are cut automatically and displayed at the Server side(May be due to the speed of Netty). I want to eliminate this. Every string starts from "8=" and ends with "10=xxx". Can anyone help me in retrieving the string from a continuous buffer as all the strings are inserted into a buffer.

Now when I run my Below code , Sometimes I get my string exactly and sometimes it shows Exception.The exception is due to the Half Strings. In the FIXMESSAGEDECODER class I wrote the logic for retrieving the string starting with "8=" and ending with "10=".

Can anyone help me how to retrieve message string exactly from the buffer without vomiting any part of the messages.

My Client Code:

 public class EchoClient {

        private final String host;
        private final int port;

        public EchoClient(String host, int port) {
            this.host = host;
            this.port = port;
        }
    public void start() throws Exception{
    EventLoopGroup group = new NioEventLoopGroup();
    try{
     Bootstrap b = new Bootstrap();
     b.group(group).channel(NioSocketChannel.class)
             .remoteAddress(new InetSocketAddress(host, port))
             .handler(new ChannelInitializer<SocketChannel>(){

             @Override
             public void initChannel(SocketChannel ch) throws Exception{
             ch.pipeline().addLast(new EchoClientHandler());
             }
             });

                ChannelFuture future = b.connect().sync();
               future.channel().closeFuture().sync();
         }

            finally {
                group.shutdownGracefully().sync();
            }
        }

        public static void main (String [] args) throws Exception {
            new EchoClient("127.0.0.1", 11235).start();
        }
    }

My ClientHandler :

public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf>{

@Override
 public void channelActive(ChannelHandlerContext ctx){
   System.out.println("Connected");
   int i=0;
   while(i<100){
ctx.writeAndFlush(Unpooled.copiedBuffer("8=FIX.4.29=0007935=A49=TTDS68AO56=RaviEx34=152=20170427-14:05:04.572108=60141=Y98=010=242\n", 
CharsetUtil.UTF_8));

  i++;
  }
}

 @Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
   System.out.println("Client received: " + in.toString(CharsetUtil.UTF_8));
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause){
     cause.printStackTrace();
     ctx.close();
   }
}

My Server:

public class EchoServer{

 private final int port;
 public EchoServer(int port) {
      this.port = port;
 }

 public void start() throws Exception {
     EventLoopGroup group = new NioEventLoopGroup();
     try {
           ServerBootstrap b = new ServerBootstrap();
           b.group(group)
            .channel(NioServerSocketChannel.class)
            .localAddress(new InetSocketAddress(port))
            .childHandler(new ChannelInitializer<SocketChannel>() {
             @Override
              public void initChannel(SocketChannel ch) throws Exception {
              System.out.println("New client connected: " + ch.localAddress());
              ch.pipeline().addLast(new FixMessageDecoder());
              }
            });

         ChannelFuture f = b.bind().sync();
         f.channel().closeFuture().sync();
     }
     finally {
                group.shutdownGracefully().sync();
            }
        }

        public static void main (String [] args) throws Exception {
        new EchoServer(11235).start();
        }
}

My FixMessage Decoder:

public class FixMessageDecoder extends MessageToMessageDecoder<ByteBuf> {

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception{
  String messg = in.toString(CharsetUtil.UTF_8);
  String str = messg.substring(messg.indexOf("8"), messg.lastIndexOf("10")+6);
  System.out.println(str);
 }
}   

回答1:


Unfortunately, there is no guarantee that your string will come at once as a whole. It could be that when the decoder first called, the buffer will contain a piece of string such as [8=...], and on the second call there will be [...10=XXX]. Another point is that you can get your string and a part of next string like [8=...10=XXX8=...]. And you have to think of better line detectors than just numbers 8 and 10. If you are sure that at this line pattern like 8= and 10=XXX is used only once, then use it.

I can suggest you to rewrite your decoder in Test-driven development style. Fortunately, decoders are very easy to test. First you write a lot of tests, where you describe so many possible variants of the incoming buffer (full string, part of string, two strings at once) as you can think of. Then you write your decoder to pass all this tests.



来源:https://stackoverflow.com/questions/44172630/how-to-retrieve-a-string-when-there-is-a-continuous-flow-of-the-messages-at-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!