[自己做个游戏服务器一]搞清楚游戏通信协议之protobuf的方方面面,评论继续送书

Posted 香菜聊游戏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[自己做个游戏服务器一]搞清楚游戏通信协议之protobuf的方方面面,评论继续送书相关的知识,希望对你有一定的参考价值。

目录

1、protobuf 环境搭建

2、protobuf 语法

2.1 注释规则

2.2 数据类型

2.3 默认值规则

2.4 protobuf 选项

2.5 protoc 生成java文件

3、idea 生成插件

3.1 GenProtobuf

3.2 protobuf

4、序列化和 反序列化

4.1 常规序列化和反序列化

4.2 通用的反序列化

5、protostuff

6、总结


最近准备启动写个gameserver的计划,所以开始准备,网络协议方面准备使用protobuf ,这也是现在最流行的,最多使用的,所以今天就写下protobuf,虽然在项目中也一直在使用,但是也只是惯性使然,今天就全面的复习下,避免在使用的时候卡壳。开始吧。

注:因为使用java的缘故,所以我就我的经验写下protobuf在java中的使用,因为其他的语言不是很熟,同时经验不多,但是大同小异。

1、protobuf 环境搭建

protobuf是由Google开发的一套对数据结构进行序列化的方法,可用做通信协议,数据存储格式,等等。其特点是不限语言、不限平台、扩展性强,就像XML一样。与XML相比,protobuf有以下特点:

1.1 protobuf 的版本

最新版本地址:Releases · protocolbuffers/protobuf · GitHub

Maven 依赖配置,直接放进去,不用想太多

        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.18.0</version>
        </dependency>

1.2 proto编译器

将主页一直往下拉,可以看到protoc的各种系统版本,根据自己的操作系统选择,我的是64位的win10 ,所以选择了win64,下载后解压就好,等会使用

2、protobuf 语法

proto3 的语法文档 :https://developers.google.com/protocol-buffers/docs/proto3

syntax = "proto3";
​
message SearchRequest 
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;

2.1 注释规则

为你的.proto 添加注释,使用 C/C++风格的 // 或者 /* ... */ 语法.

/* SearchRequest represents a search query, with pagination options to
 * indicate which results to include in the response. */
​
message SearchRequest 
  string query = 1;
  int32 page_number = 2;  // Which page number do we want?
  int32 result_per_page = 3;  // Number of results to return per page.

2.2 数据类型

基本上也都是常规的数据类型

数值: int32,int64,float ,double ,s开头(可变的,也就是编码的时候更紧凑),u开头(也就是无符号的,只能是正值),fix(固定长度的,一般不怎么用)

布尔值:bool

字符串:string

枚举 : enum

列表:repeated

二进制:bytes

基本上常用的也就是这些简单的类型,没什么特殊的。

2.3 默认值规则

定义了数据类型的,在不传的时候的默认值的规则是什么,下面以Java 为主

  • string:默认值是”“

  • bool : 默认值 是false

  • 数值类型:默认值是0,0.f或者0.D.

  • 枚举:默认值是第一个枚举值,也就是0

  • message 复合类型:在Java中时null.

    message SearchResponse 
      repeated Result results = 1;
    
    ​
    message Result 
      string url = 1;
      string title = 2;
      repeated string snippets = 3;
    

2.4 protobuf 选项

protobuf 提供了一些选项设置生成的proto文件

option java_package = "com.example.foo";
option java_outer_classname = "Ponycopter";
option java_multiple_files = true;
option optimize_for = CODE_SIZE;
​

option java_package = "com.example.foo"; 生成的java文件所在的包名

option java_outer_classname = "Ponycopter";生成的类的名字

option java_multiple_files = true;如果是false 则整个proto文件生成在一个java文件中,true 则一个message 生成一个java文件,注:不写的时候默认是false

option optimize_for = CODE_SIZE;可以设置为 SPEEDCODE_SIZELITE_RUNTIM

SPEED : 代码的序列和转换等速度优先

CODE_SIZE:优化生成的代码大小

LITE_RUNTIME:生成的代码需要更少的运行时,一般不选用此选项。

2.5 protoc 生成java文件

拷贝你下载的protoc.exe 到你的proto 文件的所在地址,在文件夹shfit + 右键 ,选择打开cmd 窗口 运行下面的

protoc --java_out=./ XX.proto

--java_out 就是生成的输出地址

xx.proto 就是你要编译的proto 文件

不信你试试

3、idea 生成插件

java中开发最常用的就是IDEA 了,因为idea 的强大插件体系是真的好用,protobuf 的开发在idea中也是很方便,这里推荐两个proto的插件,助你在开发的时候如虎添翼。

3.1 GenProtobuf

生成proto 每次都输入命令有点烦的,所以有人写了插件genprotobuf ,在idea中点点就可以了,

安装:很简单,File -> Settings->Plugins,然后点击install 就可以了,等安装完成后就可以了

配置:Tools -> Config GenProtobuf

生成java文件:选择需要生成的proto文件,然后选择 quick gen protobuf rules ,可以按上一步配置的规则生成java文件

3.2 protobuf

protobuf 插件是支持proto文件的语法,对关键字进行高亮

4、序列化和 反序列化

4.1 常规序列化和反序列化

常规的使用

        SimpleMessage.Builder builder = SimpleMessage.newBuilder();
        builder.setName("香菜");
        builder.setId(1);
        builder.setIsSimple(true);
        byte[] result=builder.build().toByteArray();//序列化
​
        SimpleMessage msg;
        try 
            msg = SimpleMessage.parseFrom(result);
            System.out.println(msg);
         catch (InvalidProtocolBufferException e) 
            e.printStackTrace();
        

4.2 通用的反序列化

使用parser 进行反序列化,保存每个消息的parser,可以在启动的时候对消息进行扫描,将消息id 对应的协议进行保存

import com.google.protobuf.Parser;
import com.xin.msg.login.SimpleMessage;
​
import java.util.HashMap;
import java.util.Map;
​
public class MsgMgr 
    public static Map<Integer, Parser> msgMap = new HashMap<>();
    static 
        //  msgId - parser
        msgMap.put(1, SimpleMessage.parser());
    

​

在进行解析的时候根据消息Id获取对应的parser 转换为 对应的消息,统一转换

        Parser parser = MsgMgr.msgMap.get(headId);
        int canReadBytes = decode.readableBytes();
        byte[] data = new byte[canReadBytes];
        decode.readBytes(data);
        Object o = parser.parseFrom(data);

5、protostuff

使用protobuf 需要写proto 文件,这个文件是为了和客户端同步,其实有点烦,再把它编译成目标语言,这样使用起来就很麻烦。但是现在有了protostuff之后,就不需要依赖.proto文件了,他可以直接对POJO进行序列化和反序列化,使用起来非常简单。

github 地址 :GitHub - protostuff/protostuff: Java serialization library, proto compiler, code generatorhttps://github.com/protostuff/protostuff

maven 依赖,加到你的pom.xml就可以了

<dependency>
  <groupId>io.protostuff</groupId>
  <artifactId>protostuff-core</artifactId>
  <version>1.7.4</version>
</dependency>
<dependency>
  <groupId>io.protostuff</groupId>
  <artifactId>protostuff-runtime</artifactId>
  <version>1.7.4</version>
</dependency>

实例;

public final class Foo

    String name;
    int id;
    
    public Foo(String name, int id)
    
        this.name = name;
        this.id = id;
    

​
static void roundTrip()

    Foo foo = new Foo("foo", 1);
​
    // this is lazily created and cached by RuntimeSchema
    // so its safe to call RuntimeSchema.getSchema(Foo.class) over and over
    // The getSchema method is also thread-safe
    Schema<Foo> schema = RuntimeSchema.getSchema(Foo.class);
​
    // Re-use (manage) this buffer to avoid allocating on every serialization
    LinkedBuffer buffer = LinkedBuffer.allocate(512);
​
    // ser
    final byte[] protostuff;
    try
    
        protostuff = ProtostuffIOUtil.toByteArray(foo, schema, buffer);
    
    finally
    
        buffer.clear();
    
​
    // deser
    Foo fooParsed = schema.newMessage();
    ProtostuffIOUtil.mergeFrom(protostuff, fooParsed, schema);

​

protostuff 就不具体介绍了,官方地址也贴上了,同时我也没在项目中使用,原因就是proto 文件还要发给客户短使用,proto是和客户端进行协议沟通的桥梁,要不然就要客户端自己写proto文件了,容易造成协议不一致。

6、总结

protobuf 只是一个通信协议,虽然有很多细节,但是并不需要太过于深入,等你遇到问题的时候再查文档不晚,记住常用的数据类型,工作中不影响搬砖就可以了,加油,下一步用起来。

送书,送书,送书

随着网络技术的迅速发展,如何有效地提取并利用信息,以及如何有效地防止信息被爬取,已成为一个巨大的挑战。本书从零基础开始讲解,系统全面,案例丰富,注重实战,既适合Python程序员和爬虫爱好者阅读学习,也可以作为广大职业院校相关专业的教材或参考用书。础操作、图形处理基本操作、简单图形的绘制和对象的管理等内容

京东自营购买链接:

《Python爬虫与反爬虫开发从入门到精通》(刘延林)【摘要 书评 试读】- 京东图书

当当自营购买链接:

《Python爬虫与反爬虫开发从入门到精通》(刘延林)【简介_书评_在线阅读】 - 当当图书

大家点赞关注,三天后在留言的同学中抽取送一本书

注:如果中奖了没关注则放弃

以上是关于[自己做个游戏服务器一]搞清楚游戏通信协议之protobuf的方方面面,评论继续送书的主要内容,如果未能解决你的问题,请参考以下文章

[自己做个游戏服务器]搞清楚游戏通信协议之protobuf的方方面面,评论继续送书

猿创征文|[自己做个游戏服务器三]将二进制流转换为具体的 protobuf消息

猿创征文|[自己做个游戏服务器三]将二进制流转换为具体的 protobuf消息

猿创征文|[自己做个游戏服务器三]将二进制流转换为具体的 protobuf消息

游戏网络编程——WebSocket入门及实现自己的WebSocket协议

[自己做个游戏服务器二] 游戏服务器的基石-Netty全解析,有例子,多图解释