岳阳建设银行网站,站群软件,交互网站图,微模板网站建设TCP以流的方式进行数据传输#xff0c;上层的应用为了对消息进行区分#xff0c;往往采用如下方式
固定消息长度#xff0c;累计读取到长度和定长LEN的报文后#xff0c;就认为读取到了个完整的消息#xff0c;然后将计数器位置重置在读取下一个报文内容将回车换行符作为…TCP以流的方式进行数据传输上层的应用为了对消息进行区分往往采用如下方式
固定消息长度累计读取到长度和定长LEN的报文后就认为读取到了个完整的消息然后将计数器位置重置在读取下一个报文内容将回车换行符作为消息结束符\r\n列如FTP协议这种方式在文本中应用比较广泛将特殊分隔符作为消息结束符标志位回车换行符就是一个特殊结束分隔符(DelimiterBasedFrameDecoder)通过在消息头定义一个长度字段来标示消息的总长度(FixedLengthFrameDecoder)
Netty对以上4种做个统一抽象封装提供了四种不同解码器来解决对应问题使用起来也非常的方便了解了它们我们就不需要自己对读取的报文人工解码也不需要考虑TCP粘包和拆包的问题了…
Delimiter自定义分隔符 我将公共的部分做了一层抽离,定义成常量方便调用 public interface EchoConstant {String SEPARATOR $_;//特殊分割符号,DelimiterBasedFrameDecoder使用Integer ECHO_DELIMITER_PORT 4040;Integer ECHO_LENGTH_PORT 5050;String HOST 127.0.0.1;Integer FRAME_LENGTH 10;//固定消息长度,FixedLengthFrameDecoder使用
} 定义EchoDelimiterServer毫无疑问大部分代码和以前类似区别是多了一个日志输出以及DelimiterBasedFrameDecoder的使用 划重点在做开发调试的时候我们可以使用Netty为我们提供的LoggingHandler输出日志
public static void bind(int port) {EventLoopGroup masterGroup new NioEventLoopGroup();//线程组,含一组NIO线程,专门用来处理网络事件EventLoopGroup workerGroup new NioEventLoopGroup();try {ServerBootstrap bootstrap new ServerBootstrap();//NIO服务端启动辅助类bootstrap.group(masterGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializerSocketChannel() {Overrideprotected void initChannel(SocketChannel channel) throws Exception {ByteBuf delimiter Unpooled.copiedBuffer(EchoConstant.SEPARATOR.getBytes());channel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));channel.pipeline().addLast(new StringDecoder());channel.pipeline().addLast(new EchoServerHandler());}});//绑定端口同步等待成功,System.out.println(绑定端口,同步等待成功......);ChannelFuture future bootstrap.bind(port).sync();//等待服务端监听端口关闭future.channel().closeFuture().sync();System.out.println(等待服务端监听端口关闭......);} catch (Exception e) {e.printStackTrace();} finally {//优雅退出释放线程池masterGroup.shutdownGracefully();workerGroup.shutdownGracefully();System.out.println(优雅退出释放线程池......);}
}
Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {String body (String) msg;System.out.println(EchoDelimiterServer 接收到的消息 : body ; 当前统计: counter);body body EchoConstant.SEPARATOR;//在消息后面加上特殊分隔符ByteBuf echo Unpooled.copiedBuffer(body.getBytes());ctx.writeAndFlush(echo);//消息写出
} 定义EchoDelimiterClient public static void connect(String host, int port) {EventLoopGroup group new NioEventLoopGroup();Bootstrap bootstrap new Bootstrap();ChannelFuture future null;try {bootstrap.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializerSocketChannel() {Overrideprotected void initChannel(SocketChannel channel) throws Exception {ByteBuf delimiter Unpooled.copiedBuffer(EchoConstant.SEPARATOR.getBytes());channel.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));channel.pipeline().addLast(new StringDecoder());channel.pipeline().addLast(new EchoClientHandler());}});//发起异步请求future bootstrap.connect(host, port).sync();//等待客户端链路关闭future.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {group.shutdownGracefully();}
} 创建EchoClientHandler继承ChannelHandlerAdapter重写读取和写出事件 Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {for (int i 0; i 10; i) {ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes()));}
}Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {String body (String) msg;System.out.println(EchoDelimiterClient 接收到的消息 : body ; 当前统计: counter);
}
试验一把 分别启动EchoDelimiterServer和EchoDelimiterClient输出如下日志 绑定端口,同步等待成功......
九月 04, 2017 10:41:27 下午 io.netty.handler.logging.LoggingHandler channelRegistered
信息: [id: 0x3b1849e8] REGISTERED
九月 04, 2017 10:41:27 下午 io.netty.handler.logging.LoggingHandler bind
信息: [id: 0x3b1849e8] BIND: 0.0.0.0/0.0.0.0:4040
九月 04, 2017 10:41:27 下午 io.netty.handler.logging.LoggingHandler channelActive
信息: [id: 0x3b1849e8, /0:0:0:0:0:0:0:0:4040] ACTIVE
九月 04, 2017 10:41:33 下午 io.netty.handler.logging.LoggingHandler channelRead
信息: [id: 0x3b1849e8, /0:0:0:0:0:0:0:0:4040] RECEIVED: [id: 0xa45511cd, /127.0.0.1:50226 /127.0.0.1:4040]
EchoDelimiterServer 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:1
EchoDelimiterServer 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:2
EchoDelimiterServer 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:3
EchoDelimiterServer 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:4
EchoDelimiterServer 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:5
EchoDelimiterServer 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:6
EchoDelimiterServer 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:7
EchoDelimiterServer 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:8
EchoDelimiterServer 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:9
EchoDelimiterServer 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:10------------------------------------------------------------------------------------------------EchoDelimiterClient 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:1
EchoDelimiterClient 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:2
EchoDelimiterClient 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:3
EchoDelimiterClient 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:4
EchoDelimiterClient 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:5
EchoDelimiterClient 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:6
EchoDelimiterClient 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:7
EchoDelimiterClient 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:8
EchoDelimiterClient 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:9
EchoDelimiterClient 接收到的消息 :Hi , Levin .Welcome to Netty.; 当前统计:10