netty使用protobuf和心跳检查、断线重连

1、下载安装protoc ,本人使用3.6.1版本

https://github.com/protocolbuffers/protobuf/releases

下载protoc,选择对应的操作系统

2、user.proto文件内容如下


syntax ="proto3";

// 生成的包名

option java_package="com.pancm.protobuf";

//生成的java名 java类名不要和proto文件名一样

option java_outer_classname ="UserInfo";

message UserMsg {

// ID

    int32 id =1;

// 姓名

    string name =2;

// 年龄

    int32 age =3;

// 状态

    int32 state =4;

}


3、netty server端和client端pom文件都添加 protobuf依赖

<dependency>

<groupId>io.grpc</groupId>

<artifactId>grpc-netty</artifactId>

<version>1.15.1</version>

</dependency>


<dependency>

<groupId>io.grpc</groupId>

<artifactId>grpc-stub</artifactId>

<version>1.15.1</version>

</dependency>


<dependency>

<groupId>io.grpc</groupId>

<artifactId>grpc-protobuf</artifactId>

<version>1.15.1</version>

</dependency>


<dependency>

<groupId>com.google.protobuf</groupId>

<artifactId>protobuf-java</artifactId>

<version>3.6.1</version>

</dependency>



4、netty 服务端和客户端pom文件在build标签添加

<extensions>

<extension>

<groupId>kr.motd.maven</groupId>

<artifactId>os-maven-plugin</artifactId>

<version>1.5.0.Final</version>

</extension>

</extensions>


5、netty 服务端和客户端pom文件添加 plugin



<plugin>

<groupId>org.xolstice.maven.plugins</groupId>

<artifactId>protobuf-maven-plugin</artifactId>

<version>0.6.1</version>

<configuration>

<!-- protoc 安装目录-->

<protocExecutable>E:\protoc-3.6.1-win32\bin\protoc.exe</protocExecutable>

</configuration>

<executions>

<execution>

<goals>

<goal>compile</goal>

</goals>

</execution>

</executions>

</plugin>


6、netty服务端编译安装,生成UserInfo.java


7、netty服务端实现


package com.tcp.protobuf;

import com.pancm.protobuf.UserInfo;

import io.netty.bootstrap.ServerBootstrap;

import io.netty.channel.*;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.SocketChannel;

import io.netty.channel.socket.nio.NioServerSocketChannel;

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;

import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

public class TcpServerProto {

private static final StringIP ="127.0.0.1";

private static final int PORT =9999;

/**

* 用于分配处理业务线程的线程组个数

*/

    protected static final int BIZGROUPSIZE = Runtime.getRuntime().availableProcessors() *2;// 默认

/**

* 业务出现线程大小

*/

    protected static final int BIZTHREADSIZE =4;

/*

* NioEventLoopGroup实际上就是个线程池,

* NioEventLoopGroup在后台启动了n个NioEventLoop来处理Channel事件,

* 每一个NioEventLoop负责处理m个Channel,

* NioEventLoopGroup从NioEventLoop数组里挨个取出NioEventLoop来处理Channel

*/

    private static final EventLoopGroupbossGroup =new NioEventLoopGroup(BIZGROUPSIZE);

private static final EventLoopGroupworkerGroup =new NioEventLoopGroup(BIZTHREADSIZE);

public static void run() {

try {

ServerBootstrap b =new ServerBootstrap();

b.group(bossGroup,workerGroup)

.option(ChannelOption.SO_BACKLOG,1024)// 设置tcp缓冲区

                    .childOption(ChannelOption.SO_KEEPALIVE,true)

.channel(NioServerSocketChannel.class)

.childHandler(new ChannelInitializer() {

@Override

                        public void initChannel(SocketChannel ch)throws Exception {

ChannelPipeline pipeline = ch.pipeline();

//入参说明: 读超时时间、写超时时间、所有类型的超时时间、时间格式

//超时处理 如果30秒没有接受客户端的心跳

                            ch.pipeline().addLast(new IdleStateHandler(30,0,0, TimeUnit.SECONDS));

// 解码和编码,应和客户端一致

//传输的协议 Protobuf

                            ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());

ch.pipeline().addLast(new ProtobufDecoder(UserInfo.UserMsg.getDefaultInstance()));

ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());

ch.pipeline().addLast(new ProtobufEncoder());

// 处理网络IO

                            pipeline.addLast(new NettyServerHandlerProto());

}

});

// 绑定端口 同步等待绑定成功

            ChannelFuture f = b.bind(PORT).sync();// (7)

// 等到服务端监听端口关闭

            f.channel().closeFuture().sync();

System.out.println("TCP服务器已启动");

}catch (InterruptedException e) {

System.out.println(e);

}

}

protected static void shutdown() {

// 优雅释放线程资源

        workerGroup.shutdownGracefully();

bossGroup.shutdownGracefully();

}

}




8、NettyServerHandlerProto


package com.tcp.protobuf;

import com.pancm.protobuf.UserInfo;

import io.netty.channel.ChannelHandlerContext;

import io.netty.channel.ChannelInboundHandlerAdapter;

import io.netty.handler.timeout.IdleState;

import io.netty.handler.timeout.IdleStateEvent;

import io.netty.util.ReferenceCountUtil;

/**

* @Description

* @Date 2019/10/17 15:56

* @Author zsj

*/

public class NettyServerHandlerProtoextends ChannelInboundHandlerAdapter {

/**

* 空闲次数

*/

    private int idle_count=1;

/**

* 发送次数

*/

    private int count =1;

/**

* 建立连接时,发送一条消息

*/

    @Override

    public void channelActive(ChannelHandlerContext ctx)throws Exception {

System.out.println("连接的客户端地址:" + ctx.channel().remoteAddress());

UserInfo.UserMsg userMsg = UserInfo.UserMsg.newBuilder().setId(1).setAge(18).setName("xuwujing").setState(0)

.build();

ctx.writeAndFlush(userMsg);

super.channelActive(ctx);

}

/**

* 超时处理 如果30秒没有接受客户端的心跳,就触发; 如果超过两次,则直接关闭;

*/

    @Override

    public void userEventTriggered(ChannelHandlerContext ctx, Object obj)throws Exception {

if (objinstanceof IdleStateEvent) {

IdleStateEvent event = (IdleStateEvent) obj;

if (IdleState.READER_IDLE.equals(event.state())) {// 如果读通道处于空闲状态,说明没有接收到心跳命令

                System.out.println("已经30秒没有接收到客户端的信息了");

if (idle_count >1) {

System.out.println("关闭这个不活跃的channel");

ctx.channel().close();

}

idle_count++;

}

}else {

super.userEventTriggered(ctx, obj);

}

}

/**

* 业务逻辑处理

*/

    @Override

    public void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {

System.out.println("第" +count +"次" +",服务端接受的消息:" + msg);

try {

// 如果是protobuf类型的数据

            if (msginstanceof UserInfo.UserMsg) {

UserInfo.UserMsg userState = (UserInfo.UserMsg) msg;

if (userState.getState() ==1) {

System.out.println("客户端业务处理成功!");

}else if (userState.getState() ==2) {

System.out.println("接受到客户端发送的心跳!");

}else {

System.out.println("未知命令!");

}

}else {

System.out.println("未知数据!" + msg);

return;

}

}catch (Exception e) {

e.printStackTrace();

}finally {

ReferenceCountUtil.release(msg);

}

count++;

}

/**

* 异常处理

*/

    @Override

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {

cause.printStackTrace();

ctx.close();

}

}



客户端实现 待续。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349