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的整合(一)的更多相关文章

  1. Netty学习——Netty和Protobuf的整合(二)

    Netty学习——Netty和Protobuf的整合(二) 这程序是有瑕疵的,解码器那里不通用,耦合性太强,有两个很明显的问题,但是要怎么解决呢?如:再加一个内部类型 Person2,之前的代码就不能 ...

  2. netty学习--netty源码中的部分util方法

    io.netty.buffer.AbstractByteBuf#calculateNewCapacity  申请内存空间 private int calculateNewCapacity(int mi ...

  3. Netty学习篇③--整合springboot

    经过前面的netty学习,大概了解了netty各个组件的概念和作用,开始自己瞎鼓捣netty和我们常用的项目的整合(很简单的整合) 项目准备 工具:IDEA2017 jar包导入:maven 项目框架 ...

  4. Netty学习第一节Netty的总体概况

    一.Netty简介 什么是Netty? 1.高性能事件驱动,异步非阻塞的IO加载开源框架. 它是由JBoss提供,用于建立TCP等底层链接.基于Netty可以建立高性能的HTTP服务器,快速开发高性能 ...

  5. [置顶] Netty学习总结(1)——Netty入门介绍

    1.Netty是什么? Netty是一个基于JAVA NIO类库的异步通信框架,它的架构特点是:异步非阻塞.基于事件驱动.高性能.高可靠性和高可定制性. 2.使用Netty能够做什么? 开发异步.非阻 ...

  6. Netty学习——Thrift的入门使用

    Netty学习——Thrift的入门使用 希望你能够,了解并使用它.因为它是一个效率很高的框架 官网地址:http://thrift.apache.org/ 1.Thrift数据类型 一门技术如果需要 ...

  7. Netty学习——protoc的新手使用流程

    Netty学习——protoc的新手使用流程 关于学习的内容笔记,记下来的东西等于又过了一次脑子,记录的更深刻一些. 1. 使用IDEA创建.proto文件,软件会提示你安装相应的语法插件 安装成功之 ...

  8. netty学习资料

    netty学习资料推荐官方文档和<netty权威指南>和<netty in action>这两本书.下面收集下网上分享的资料 netty官方参考文档 Netty 4.x Use ...

  9. Netty学习之客户端创建

    一.客户端开发时序图 图片来源:Netty权威指南(第2版) 二.Netty客户端开发步骤 使用Netty进行客户端开发主要有以下几个步骤: 1.用户线程创建Bootstrap Bootstrap b ...

随机推荐

  1. 关于 Java 中多线程的面试问题 详解

    多线程细节: 1. 面试题: sleep 方法 和 wait 方法异同点是什么? 相同点: 可以让线程 处于 冻结状态. 不同点: 1. sleep 必须指定时间 wait 可以指定时间, 也可以不指 ...

  2. vue踩坑 导出new Vue.Store首字母要大写

    控制台报错  : Uncaught TypeError: vuex__WEBPACK_IMPORTED_MODULE_6__.default.store is not a constructor 根据 ...

  3. pxe批量部署脚本

    #!/bin/bash #检查环境 setenforce 0 sed -i 's/=enforce/=disabled/g' /etc/selinux/config systemctl restart ...

  4. 实现支持多用户在线的FTP程序(C/S)

    1. 需求 1. 用户加密认证 2. 允许多用户登录 3. 每个用户都有自己的家目录,且只能访问自己的家目录 4. 对用户进行磁盘分配,每一个用户的可用空间可以自己设置 5. 允许用户在ftp ser ...

  5. RHEL7-Vsftpd匿名用户

    实现:匿名用户创建目录,可以上传.下载文件,但是不可删除文件,禁止本地用户登陆. Vsftpd.conf部分参数 第一步:虚拟机挂载镜像 略 第二步:执行挂载命令 略 第三步:编写yum仓库文件 略 ...

  6. Chrome Extension 小试牛刀

    自从有了Chrome以后,就喜欢上了这个浏览器,从此IE 886了. 以前作爬虫,做登录,做数据采集,做数据处理等各种功能,后来H5出来后,出现了,除了Session/Cookie 出了Local S ...

  7. windows7设置定时任务运行ThinkPHP框架程序

    1. 设置Windows的任务计划 可以参考win7计划任务的设置方法 2. 新建Windows执行文件bat 新建cron.bat文件,内容如下: D: cd \wamp\www\tp32 D:\w ...

  8. hdu 1171 Big Event in HDU (01背包, 母函数)

    Big Event in HDU Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  9. npm报错:无法加载文件 D:\nodejs\node_global\webpack.ps1,因为在此系统上禁止运行脚本

    npm报错 在 windows终端输入 vue init webpack app, 创建一个名为 app 的 Vue 项目时报错如下: 无法加载文件 D:\nodejs\node_global\web ...

  10. Linux关机、重启、退出

    序号 命令 说明 1 shutdown -h now 立即关机 2 shutdown -h +10 "请各位退出"     十分钟后关机,同时广播通告“请各位退出” 3 shutd ...