Netty学习——Netty和Protobuf的整合(一)
Netty学习——Netty和Protobuf的整合
Protobuf作为序列化的工具,将序列化后的数据,通过Netty来进行在网络上的传输
1.将proto文件里的java包的位置修改一下,然后再执行一下protoc
异常捕获:启动服务器端正常,在启动客户端的时候,发送消息,报错
警告: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.handler.codec.DecoderException: com.google.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero).
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:)
at io.netty.util.concurrent.SingleThreadEventExecutor$.run(SingleThreadEventExecutor.java:)
at io.netty.util.internal.ThreadExecutorMap$.run(ThreadExecutorMap.java:)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:)
at java.lang.Thread.run(Thread.java:)
Caused by: com.google.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero).
at com.google.protobuf.InvalidProtocolBufferException.invalidTag(InvalidProtocolBufferException.java:)
at com.google.protobuf.CodedInputStream$ArrayDecoder.readTag(CodedInputStream.java:)
at com.dawa.netty.sixthexample.MyDataInfo$Person.<init>(MyDataInfo.java:)
at com.dawa.netty.sixthexample.MyDataInfo$Person.<init>(MyDataInfo.java:)
at com.dawa.netty.sixthexample.MyDataInfo$Person$.parsePartialFrom(MyDataInfo.java:)
at com.dawa.netty.sixthexample.MyDataInfo$Person$.parsePartialFrom(MyDataInfo.java:)
at com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:)
at io.netty.handler.codec.protobuf.ProtobufDecoder.decode(ProtobufDecoder.java:)
at io.netty.handler.codec.protobuf.ProtobufDecoder.decode(ProtobufDecoder.java:)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:)
... more 十二月 , :: 上午 io.netty.channel.DefaultChannelPipeline onUnhandledInboundException
警告: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.handler.codec.DecoderException: com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length.
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:)
at io.netty.util.concurrent.SingleThreadEventExecutor$.run(SingleThreadEventExecutor.java:)
at io.netty.util.internal.ThreadExecutorMap$.run(ThreadExecutorMap.java:)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:)
at java.lang.Thread.run(Thread.java:)
Caused by: com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length.
at com.google.protobuf.InvalidProtocolBufferException.truncatedMessage(InvalidProtocolBufferException.java:)
at com.google.protobuf.CodedInputStream$ArrayDecoder.readRawByte(CodedInputStream.java:)
at com.google.protobuf.CodedInputStream$ArrayDecoder.readRawVarint64SlowPath(CodedInputStream.java:)
at com.google.protobuf.CodedInputStream$ArrayDecoder.readRawVarint32(CodedInputStream.java:)
at com.google.protobuf.CodedInputStream$ArrayDecoder.readTag(CodedInputStream.java:)
at com.dawa.netty.sixthexample.MyDataInfo$Person.<init>(MyDataInfo.java:)
at com.dawa.netty.sixthexample.MyDataInfo$Person.<init>(MyDataInfo.java:)
at com.dawa.netty.sixthexample.MyDataInfo$Person$.parsePartialFrom(MyDataInfo.java:)
at com.dawa.netty.sixthexample.MyDataInfo$Person$.parsePartialFrom(MyDataInfo.java:)
at com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:)
at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:)
at io.netty.handler.codec.protobuf.ProtobufDecoder.decode(ProtobufDecoder.java:)
at io.netty.handler.codec.protobuf.ProtobufDecoder.decode(ProtobufDecoder.java:)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:)
... more
开始找问题:
1.io.netty.handler.codec.DecoderException: 在解码过程中出错,可能是服务器端出的错
2.Caused by: com.google.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero).
3.While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length.
检查了一下代码:猜测了一下:成了,效果图如下
可怕,原因竟然出现在编码器添加的顺序不同导致的: 正确的顺序是这样的:
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//这里和之前的不一样了,但也就是处理器的不一样
//编解码处理器,protobuf提供的专门的编解码器.4个处理器
pipeline.addLast(new ProtobufVarint32FrameDecoder());
//Decoder是重点,解码器,将字节码转换成想要的数据类型
//参数 messageLite,外层的要转换的类的实例
pipeline.addLast(new ProtobufDecoder(MyDataInfo.Person.getDefaultInstance()));
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new TestServerHandler());
}
接下来存放一下完整的客户端和服务器端的代码
proto文件
yntax ="proto2"; package com.dawa.protobuf; option optimize_for = SPEED;
option java_package ="com.dawa.netty.sixthexample";
option java_outer_classname = "MyDataInfo"; message Person{
required string name = ;
optional int32 age = ;
optional string address = ;
} message Person2{
required string name = ;
optional int32 age = ;
optional string address = ;
}
服务器端代码:
package com.dawa.netty.sixthexample; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler; /**
* @Title: TestServer
* @Author: 大娃
* @Date: 2019/12/3 10:01
* @Description:
*/
public class TestServer {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup(); try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new TestServerInitializer()); ChannelFuture channelFuture = serverBootstrap.bind().sync();
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
package com.dawa.netty.sixthexample; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; /**
* @Title: TestServerHandler
* @Author: 大娃
* @Date: 2019/12/3 10:09
* @Description: handler本身是个泛型,这里的泛型就是取 要处理的类型
*/
public class TestServerHandler extends SimpleChannelInboundHandler<MyDataInfo.Person> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, MyDataInfo.Person msg) throws Exception {
//对接受到的消息进行处理:
System.out.println(msg.getName());
System.out.println(msg.getAge());
System.out.println(msg.getAddress());
}
}
package com.dawa.netty.sixthexample; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; /**
* @Title: TestServerInitializer
* @Author: 大娃
* @Date: 2019/12/3 10:05
* @Description:
*/
public class TestServerInitializer extends ChannelInitializer<SocketChannel> { @Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//这里和之前的不一样了,但也就是处理器的不一样
//编解码处理器,protobuf提供的专门的编解码器.4个处理器
pipeline.addLast(new ProtobufVarint32FrameDecoder());
//Decoder是重点,解码器,将字节码转换成想要的数据类型
//参数 messageLite,外层的要转换的类的实例
pipeline.addLast(new ProtobufDecoder(MyDataInfo.Person.getDefaultInstance()));
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new TestServerHandler());
}
}
客户端代码
package com.dawa.netty.sixthexample; import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel; /**
* @Title: TestClient
* @Author: 大娃
* @Date: 2019/12/3 10:15
* @Description: 客户端内容
*/
public class TestClient {
public static void main(String[] args) throws Exception {
EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
.handler(new TestClientInitializer());
//注意此处,使用的是connect,不是使用的bind
ChannelFuture channelFuture = bootstrap.connect("localhost", ).sync();
channelFuture.channel().closeFuture().sync();
} finally {
eventLoopGroup.shutdownGracefully();
}
}
}
package com.dawa.netty.sixthexample; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; /**
* @Title: TestClientInitializer
* @Author: 大娃
* @Date: 2019/12/3 10:43
* @Description:
*/
public class TestClientInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//这里和之前的不一样了,但也就是处理器的不一样
//编解码处理器,protobuf提供的专门的编解码器.4个处理器
pipeline.addLast(new ProtobufVarint32FrameDecoder());
//Decoder是重点,解码器,将字节码转换成想要的数据类型
//参数 messageLite,外层的要转换的类的实例
pipeline.addLast(new ProtobufDecoder(MyDataInfo.Person.getDefaultInstance()));
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufEncoder());
//自己的处理器
pipeline.addLast(new TestClientHandler());
}
}
package com.dawa.netty.sixthexample; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; /**
* @Title: TestClientHandler
* @Author: 大娃
* @Date: 2019/12/3 10:44
* @Description:
*/
public class TestClientHandler extends SimpleChannelInboundHandler<MyDataInfo.Person> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, MyDataInfo.Person msg) throws Exception { } @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
//处于活动状态
MyDataInfo.Person person = MyDataInfo.Person.newBuilder().setName("大娃").setAge().setAddress("北京").build();
ctx.channel().writeAndFlush(person);
}
}
这程序是有瑕疵的,解码器那里不通用,耦合性太强,有两个很明显的问题,但是要怎么解决呢?
会专门写个帖子进行分析,Netty学习——Netty和Protobuf的整合(二)
Netty学习——Netty和Protobuf的整合(一)的更多相关文章
- Netty学习——Netty和Protobuf的整合(二)
Netty学习——Netty和Protobuf的整合(二) 这程序是有瑕疵的,解码器那里不通用,耦合性太强,有两个很明显的问题,但是要怎么解决呢?如:再加一个内部类型 Person2,之前的代码就不能 ...
- netty学习--netty源码中的部分util方法
io.netty.buffer.AbstractByteBuf#calculateNewCapacity 申请内存空间 private int calculateNewCapacity(int mi ...
- Netty学习篇③--整合springboot
经过前面的netty学习,大概了解了netty各个组件的概念和作用,开始自己瞎鼓捣netty和我们常用的项目的整合(很简单的整合) 项目准备 工具:IDEA2017 jar包导入:maven 项目框架 ...
- Netty学习第一节Netty的总体概况
一.Netty简介 什么是Netty? 1.高性能事件驱动,异步非阻塞的IO加载开源框架. 它是由JBoss提供,用于建立TCP等底层链接.基于Netty可以建立高性能的HTTP服务器,快速开发高性能 ...
- [置顶]
Netty学习总结(1)——Netty入门介绍
1.Netty是什么? Netty是一个基于JAVA NIO类库的异步通信框架,它的架构特点是:异步非阻塞.基于事件驱动.高性能.高可靠性和高可定制性. 2.使用Netty能够做什么? 开发异步.非阻 ...
- Netty学习——Thrift的入门使用
Netty学习——Thrift的入门使用 希望你能够,了解并使用它.因为它是一个效率很高的框架 官网地址:http://thrift.apache.org/ 1.Thrift数据类型 一门技术如果需要 ...
- Netty学习——protoc的新手使用流程
Netty学习——protoc的新手使用流程 关于学习的内容笔记,记下来的东西等于又过了一次脑子,记录的更深刻一些. 1. 使用IDEA创建.proto文件,软件会提示你安装相应的语法插件 安装成功之 ...
- netty学习资料
netty学习资料推荐官方文档和<netty权威指南>和<netty in action>这两本书.下面收集下网上分享的资料 netty官方参考文档 Netty 4.x Use ...
- Netty学习之客户端创建
一.客户端开发时序图 图片来源:Netty权威指南(第2版) 二.Netty客户端开发步骤 使用Netty进行客户端开发主要有以下几个步骤: 1.用户线程创建Bootstrap Bootstrap b ...
随机推荐
- 精心整理(含图版)|你要的全拿走!(R数据分析,可视化,生信实战)
本文首发于“生信补给站”公众号,https://mp.weixin.qq.com/s/ZEjaxDifNATeV8fO4krOIQ更多关于R语言,ggplot2绘图,生信分析的内容,敬请关注小号. 为 ...
- HtmlSpanner 使用小结 -- 安卓解析html
如何利用 HtmlSpanner解析 HTML格式 的字符串: 1. GitHub 下载HtmlSpanner项目 https://github.com/NightWhistler/HtmlSpann ...
- Python实现日志文件写入或者打印--类似于Java的Log4j
开发过Java的应该都知道Log4j的重要性,尤其是在开发测试中,能够让开发和测试人员方便找的bug,Python也有和Log4j相同功能的库那就是logging库,其功能非常强大,在开发测试中很方便 ...
- html5自动横屏的方法
html5自动横屏的方法<pre>var evt = "onorientationchange" in window ? "orientationchange ...
- Genymotion模拟器安装搜狗输入法
Genymotion模拟器默认没有中文输入法,如果在一些调试中涉及到需要输入中文则必须需要安装中文输入法. 这里以搜狗输入法为例. 这里需要注意一下几点就行: 百度下载一个搜狗输入法,需要特别注意的是 ...
- 【集合系列】- 深入浅出分析Collection中的List接口
一.List简介 List 的数据结构就是一个序列,存储内容时直接在内存中开辟一块连续的空间,然后将空间地址与索引对应. 以下是List集合简易架构图 由图中的继承关系,可以知道,ArrayList. ...
- keeplived离线安装openssl-devel依赖包
转载自素文宅博客:https://blog.yoodb.com/yoodb/article/detail/1434 由于公司业务并发比较高需要高可用使用LVS keeplived.在linux系统ce ...
- mybatis的parameterType为map,map里带有多个list
我写这个主要是为了解决sql注入 原sql有sql注入, 结果:select req_msg_id from account_message_info where req_msg_id in ('12 ...
- Java描述设计模式(21):状态模式
本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景 1.场景描述 变色龙是爬行动物,是非常奇特的动物,它有适于树栖生活的种种特征和行为,身体也会随着环境的变化而变化出适应环境的颜色 ...
- python获取随机验证码或者下发激活码
http://stackoverflow.com/questions/2823316/generate-a-random-letter-in-python >>> import ra ...