欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Netty結(jié)合Protobuf進行編解碼的方法

 更新時間:2021年06月25日 17:34:34   作者:xiah_jp  
這篇文章主要介紹了Netty結(jié)合Protobuf進行編解碼,通過文檔表述和代碼實例充分說明了如何進行使用和操作,需要的朋友可以參考下

 一般在使用netty時,數(shù)據(jù)傳輸?shù)臅r候都會選擇對傳輸?shù)臄?shù)據(jù)進行編解碼,編碼后的數(shù)據(jù)變小, 有利于在有限的帶寬下傳輸更多的數(shù)據(jù)。

由于java本身序列化的缺點較多(無法跨語言,序列化后的碼流太大,序列化的性能太低等),業(yè)界主流的編解碼框架主要有如下三個:

  1. Google的Protobuf
  2. Facebook的Thrift
  3. JBoss的Marshalling

今天我們簡單介紹一下Netty結(jié)合google的Protobuf框架進行數(shù)據(jù)的編解碼。

1. 什么是Protobuf?

Protobuf全稱是Google Protocol Buffers, 它是谷歌公司開源的一個序列化框架。

它將數(shù)據(jù)結(jié)構(gòu)以.proto文件進行描述,通過代碼生成工具可以生成對應數(shù)據(jù)結(jié)構(gòu)的POJO對象和Protobuf相關(guān)的方法和屬性。

它的特點如下:

  1. 結(jié)構(gòu)化數(shù)據(jù)存儲格式
  2. 高效的編解碼性能
  3. 語言無關(guān)、平臺無關(guān)、擴展性好
  4. 官方支持多個語言(java,c++,python,c#等)

2. 下載安裝

Protobuf已經(jīng)托管在github上,可以在release頁面下載,本案例使用的是v3.6(要下載后綴為-win32.zip的)。

下載后,將壓縮包進行解壓。這里主要用到bin目錄下的protoc.exe。

3. 定義好proto文件

SubscribeReq.proto

// 區(qū)分不同的protobuf版本,必須有
syntax = "proto2";
 
package netty;
// 生成的目標類的包路徑
option java_package = "cn.ddlover.nettystudy.protobuf";
// 生成的目標類的名字
option java_outer_classname = "SubscribeReqProto";
 
message SubscribeReq{
    required int32 subReqID = 1;
    required string userName = 2;
    required string productName = 3;
    repeated string address = 4;
}

SubscribeResp.proto

syntax = "proto2";
package netty;
 
option java_package = "cn.ddlover.nettystudy.protobuf";
option java_outer_classname = "SubscribeRespProto";
 
message SubscribeResp{
    required int32 subReqID = 1;
    required int32 respCode = 2;
    required string desc = 3;
}

此時項目結(jié)構(gòu)如下

重點關(guān)注一下兩個proto文件的位置,是位于項目的根路徑下

4. 分別執(zhí)行以下命令

D:\xhb\protoc-3.6.1-win32\bin\protoc.exe --java_out=.\src\main\java SubscribeResp.proto 

D:\xhb\protoc-3.6.1-win32\bin\protoc.exe --java_out=.\src\main\java SubscribeReq.proto 

這里需要把protoc.exe的位置換成自己的, --java_out命令設(shè)置的是proto文件中java_package指令的父目錄。

5. 此時項目結(jié)構(gòu)如下

下面開始代碼方面的開發(fā),

1. 先貼一波maven的配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>cn.ddlover</groupId>
    <artifactId>nettystudy</artifactId>
    <version>1.0-SNAPSHOT</version>
 
 
    <properties>
        <java.version>1.8</java.version>
    </properties>
 
    <dependencies>
        <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.33.Final</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.6.1</version>
        </dependency>
 
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
        </dependency>
    </dependencies>
</project>

2. 這里貼上完整代碼的項目結(jié)構(gòu)

3. SubReqServer.java

 
import cn.ddlover.nettystudy.handler.SubReqServerHandler;
import cn.ddlover.nettystudy.protobuf.SubscribeReqProto;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
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.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
 
/**
 * Protobuf版本圖書訂購代碼
 */
public class SubReqServer {
    private static final int PORT = 8080;
 
    public static void main(String[] args) {
        bind(PORT);
    }
 
    private static void bind(int port) {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
 
        ServerBootstrap b = new ServerBootstrap();
        try {
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 100)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            // 半包處理
                            socketChannel.pipeline().addLast(new ProtobufVarint32FrameDecoder());
                            socketChannel.pipeline().addLast(new ProtobufDecoder(SubscribeReqProto.SubscribeReq.getDefaultInstance()));
                            socketChannel.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
                            socketChannel.pipeline().addLast(new ProtobufEncoder());
                            socketChannel.pipeline().addLast(new SubReqServerHandler());
                        }
                    });
            ChannelFuture future = b.bind(port).sync();
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

4. SubReqServerHandler.java

import cn.ddlover.nettystudy.protobuf.SubscribeReqProto;
import cn.ddlover.nettystudy.protobuf.SubscribeRespProto;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
 
public class SubReqServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        SubscribeReqProto.SubscribeReq req = (SubscribeReqProto.SubscribeReq)msg;
 
        if ("張三".equals(req.getUserName())) {
            System.out.println("Server accept clietn subscribe req : ["+req.toString()+"]");
            ctx.writeAndFlush(resp(req.getSubReqID()));
        }
    }
 
    private SubscribeRespProto.SubscribeResp resp(int subReqID) {
        SubscribeRespProto.SubscribeResp.Builder builder = SubscribeRespProto.SubscribeResp.newBuilder();
        builder.setSubReqID(subReqID);
        builder.setRespCode(0);
        builder.setDesc("netty書籍下單成功,3天后將會送到你的住處");
        return builder. build();
    }
 
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

5. SubReqClient.java

import cn.ddlover.nettystudy.handler.SubReqClientHandler;
import cn.ddlover.nettystudy.protobuf.SubscribeRespProto;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
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;
 
public class SubReqClient {
    private static final String HOST = "localhost";
    private static final int PORT = 8080;
 
    public static void main(String[] args) {
        connect(HOST, PORT);
    }
 
    private static void connect(String host, int port) {
        EventLoopGroup group = new NioEventLoopGroup();
 
        Bootstrap b = new Bootstrap();
        try {
            b.group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
 
                            // 半包處理
                            socketChannel.pipeline().addLast(new ProtobufVarint32FrameDecoder());
                            socketChannel.pipeline().addLast(new ProtobufDecoder(SubscribeRespProto.SubscribeResp.getDefaultInstance()));
                            socketChannel.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
                            socketChannel.pipeline().addLast(new ProtobufEncoder());
                            socketChannel.pipeline().addLast(new SubReqClientHandler());
                        }
                    });
            ChannelFuture f = b.connect(host, port).sync();
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            group.shutdownGracefully();
        }
    }
}

6. SubReqClientHandler.java

import cn.ddlover.nettystudy.protobuf.SubscribeReqProto;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
 
import java.util.ArrayList;
import java.util.List;
 
public class SubReqClientHandler extends ChannelInboundHandlerAdapter {
 
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        for (int i =0;i<10;i++) {
            ctx.write(subReq(i));
        }
        ctx.flush();
    }
 
    private SubscribeReqProto.SubscribeReq subReq(int i) {
        SubscribeReqProto.SubscribeReq.Builder builder = SubscribeReqProto.SubscribeReq.newBuilder();
        builder.setSubReqID(i);
        builder.setUserName("張三");
        builder.setProductName("Netty Book");
        List<String> address = new ArrayList<>();
        address.add("NanJing YuHuaTai");
        address.add("BeiJing LiuLiChang");
        address.add("ShenZhen HongShuLin");
        builder.addAllAddress(address);
        return builder.build();
    }
 
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("Receive server response : ["+ msg +"]");
    }
 
 
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

代碼部分到此就結(jié)束了,然后分別運行SubReqServerSubReqClient, 就可以發(fā)現(xiàn)運行成功了。

這里要注意的事,調(diào)用toString的時候,中文在控制臺打印的是字節(jié),而調(diào)用對應屬性的getter方法的時候,是可以做中文的判斷的,顯然這里protobuf的toString沒有被修改好呀。

當然,我們也可以發(fā)現(xiàn),netty本身已經(jīng)封裝好了對谷歌的protobuf的支持。Netty還是很強大的。

到此這篇關(guān)于Netty結(jié)合Protobuf進行編解碼的文章就介紹到這了,更多相關(guān)Netty結(jié)合Protobuf編解碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java 10 局部變量類型推斷淺析

    Java 10 局部變量類型推斷淺析

    這篇文章主要介紹了Java 10 局部變量類型推斷淺析,Java 10 引進一種新的閃閃發(fā)光的特性叫做局部變量類型推斷。文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,,需要的朋友可以參考下
    2019-06-06
  • mybatis if test條件判斷語句中的判斷問題分析

    mybatis if test條件判斷語句中的判斷問題分析

    這篇文章主要介紹了mybatis if test條件判斷語句中的判斷問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • mybatis映射文件mapper.xml的具體寫法

    mybatis映射文件mapper.xml的具體寫法

    在開發(fā)過程中,需要開發(fā)人員配置mapper映射文件,本文主要介紹了mybatis映射文件mapper.xml的具體寫法,感興趣的可以了解一下
    2021-09-09
  • 詳解Spring注解驅(qū)動開發(fā)之屬性賦值

    詳解Spring注解驅(qū)動開發(fā)之屬性賦值

    今天帶大家學習Spring注解驅(qū)動開發(fā)的相關(guān)知識,文中有非常詳細的代碼示例,對正在學習Java的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • SpringBoot深入講解單元測試與熱部署應用

    SpringBoot深入講解單元測試與熱部署應用

    這篇文章介紹了SpringBoot單元測試與熱部署,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • Java8中流的性能及流的幾個特性

    Java8中流的性能及流的幾個特性

    流(Stream)是Java8為了實現(xiàn)最佳性能而引入的一個全新的概念。接下來通過本文給大家分享Java8中流的性能,需要的朋友參考下吧
    2017-11-11
  • java垃圾回收之實現(xiàn)并行GC算法

    java垃圾回收之實現(xiàn)并行GC算法

    這篇文章主要為大家介紹了java垃圾回收之實現(xiàn)并行GC算法的詳細講解,讓我們看看并行垃圾收集器的GC日志長什么樣,?從中我們可以得到哪些有用信息
    2022-01-01
  • Java?Spring?Dubbo三種SPI機制的區(qū)別

    Java?Spring?Dubbo三種SPI機制的區(qū)別

    這篇文章主要介紹了Java?Spring?Dubbo三種SPI機制的區(qū)別,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下
    2022-08-08
  • mybatis 如何返回list<String>類型數(shù)據(jù)

    mybatis 如何返回list<String>類型數(shù)據(jù)

    這篇文章主要介紹了mybatis 如何返回list<String>類型數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java中幾種常用數(shù)據(jù)庫連接池的使用

    Java中幾種常用數(shù)據(jù)庫連接池的使用

    數(shù)據(jù)庫連接池在編寫應用服務是經(jīng)常需要用到的模塊,太過頻繁的連接數(shù)據(jù)庫對服務性能來講是一個瓶頸,使用緩沖池技術(shù)可以來消除這個瓶頸,本文就來介紹Java常見的幾種,感興趣的可以了解一下
    2021-05-05

最新評論