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 ...
随机推荐
- C语言I博客作业07
这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/SE2019-1/homework/9931 我在这个课程的目标 ...
- python 3.7.5 官方tutorial 学习笔记
用了好久python,还没有完整看过官方的tutorial,这几天抽空看了下,还是学到些东西 --- Table of Contents 1. 课前甜点 2. 使用 Python 解释器 2.1. 调 ...
- 使用jieba分析小说人物出现次数
分析: 1. 读取小说,以读的形式打开 with open('文件名.txt','r',encoding='utf8') as f: str = f.read() 2. 切割小说 ret = jieb ...
- [考试反思]1001csp-s模拟测试(b):逃离
如你所见,b组题,除了NC乱入直奔T2抢了我一个首杀以外A层学过FFT的人都没有参加. 竞争压力很小,题又简单,所以就造就了6个AK. 然而并不计入总分,我仍然稳在第二机房. T1lyl16分钟切掉我 ...
- 死磕 java线程系列之终篇
(手机横屏看源码更方便) 简介 线程系列我们基本就学完了,这一个系列我们基本都是围绕着线程池在讲,其实关于线程还有很多东西可以讲,后面有机会我们再补充进来.当然,如果你有什么好的想法,也可以公从号右下 ...
- Unix/Linux 从哪儿来?那些改变世界的人们...
昨天看文章时发现自己对 linux 操作系统不够了解,还记得 17 年时听过老师的一些课,对 linux 的历史有一点了解,不过当时并没有记录笔记,现在已经忘的差不多了. 这次从网上找资料,又重新看了 ...
- UiPath之基础知识(一)
各位小伙伴,大家好.在10月份小U的微信订阅号做了一个投票,主题是UiPath目前已经掌握的程度. 从投票的结果来看,有一半以上的人还是刚刚起步,为了帮助刚刚起步的小伙伴,准备陆续发布一些基础性的内容 ...
- 2. 彤哥说netty系列之IO的五种模型
你好,我是彤哥,本篇是netty系列的第二篇. 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识. 简介 本文将介绍linux中的五种IO模型,同时也会介绍阻塞/非阻塞与同步/异步的区别. ...
- Vue基础系列(二)——Vue中的methods属性
写在前面的话: 文章是个人学习过程中的总结,为方便以后回头在学习. 文章中会参考官方文档和其他的一些文章,示例均为亲自编写和实践,若有写的不对的地方欢迎大家指出. 作者简介: 一个不知名的前端开发 ...
- C语言程序设计100例之(10):最大公约数
例10 最大公约数 问题描述 有三个正整数a,b,c(0<a,b,c<10^6),其中c不等于b.若a和c的最大公约数为b,现已知a和b,求满足条件的最小的c. 输入数据 第 ...