[自己做个游戏服务器一]搞清楚游戏通信协议之protobuf的方方面面

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

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


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


1、protobuf 环境搭建


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


1.1 protobuf 的版本


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

2fca316379914af4b35f7b14a5dc7c98~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg

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


<dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java</artifactId>
        <version>3.18.0</version>
    </dependency>
复制代码


1.2 proto编译器


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


67351dd5e592496d926fcb78739d10b1~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg

2、protobuf 语法


proto3 的语法文档 :developers.google.com/protocol-bu…


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;可以设置为 SPEED, CODE_SIZE, LITE_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 就可以了,等安装完成后就可以了

7e1b4580bf60482085b072ee138fa2e8~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg

配置:Tools -> Config GenProtobuf

fb4cb1c148434ed382f4b0d367f1e462~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg

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

90f3a2c449a54e068b91fa4d48db4ffb~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg

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

4feb9cf63ae14cce8ed37b3696d20d3b~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg

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

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

目录
相关文章
|
3天前
|
弹性计算 固态存储
玩转阿里云游戏服务器:阿里云幻兽帕鲁Palworld游戏专属服务器搭建保姆级流程
对于热爱《幻兽帕鲁》的玩家们来说,与好友一起联机冒险无疑是游戏的一大乐趣。但如何快速搭建一个专属服务器,让你和朋友轻松“抓帕鲁”呢?本文将为您提供阿里云极简部署幻兽帕鲁专属服务器的指引,让您仅需轻点三次鼠标,3秒轻松开服!
|
3天前
|
弹性计算 Linux Windows
2024年阿里云《幻兽帕鲁/Palworld》如何搭建多人游戏专用服务器,图文攻略
《幻兽帕鲁》无疑是近期游戏界的焦点,其独特的开放世界与生存制作玩法吸引了众多玩家。但你知道吗?与好友一同在这个世界中冒险,其实更加有趣!今天,就为大家带来详细的图文攻略,教你在阿里云上快速搭建《幻兽帕鲁》的多人游戏专用服务器。
|
3天前
|
弹性计算 数据安全/隐私保护
2024年阿里云Palworld/幻兽帕鲁多人游戏专用服务器搭建部署指南
随着幻兽帕鲁/Palworld的风靡,越来越多的玩家渴望与好友在这个神秘世界中并肩作战。但官方服务器的不稳定让许多玩家头疼不已。别担心,今天就来教大家如何一键搭建属于自己的幻兽帕鲁云服务器,让你和好友的游戏体验更加顺畅!
|
3天前
|
弹性计算 数据安全/隐私保护
2024年Palworld/幻兽帕鲁多人游戏专用服务器:从0到1,手把手指南
随着幻兽帕鲁/Palworld的风靡,越来越多的玩家渴望与好友在这个神秘世界中并肩作战。但官方服务器的不稳定让许多玩家头疼不已。别担心,今天就来教大家如何一键搭建属于自己的幻兽帕鲁云服务器,让你和好友的游戏体验更加顺畅!
|
3天前
|
弹性计算 固态存储
2024年阿里云如何自建《Palworld/幻兽帕鲁》多人游戏专用服务器详细教程
想要和朋友在《幻兽帕鲁》的世界里自由冒险,却苦于没有合适的服务器?别担心,现在就来教您如何在三次点击之内,轻松搭建自己的专属《幻兽帕鲁》服务器!
39 1
|
3天前
|
弹性计算 数据安全/隐私保护
Palworld/幻兽帕鲁多人游戏新篇章:2024年手把手指南教你自建服务器
越来越多的玩家渴望与好友在这个神秘世界中并肩作战。但官方服务器的不稳定让许多玩家头疼不已。别担心,今天就来教大家如何一键搭建属于自己的幻兽帕鲁云服务器,让你和好友的游戏体验更加顺畅!
|
3天前
|
网络协议 Ubuntu Java
如何使用MCSM搭建我的世界Java版服务器并实现远程联机游戏
如何使用MCSM搭建我的世界Java版服务器并实现远程联机游戏
30 0
|
3天前
|
网络协议 Java Windows
打造个人的Minecraft服务器:Java+cpolar实现我的世界联机游戏
打造个人的Minecraft服务器:Java+cpolar实现我的世界联机游戏
116 0
|
3天前
|
弹性计算 运维 安全
畅享幻兽帕鲁:快速搭建稳定服务器,与小伙伴畅游游戏世界!
畅享幻兽帕鲁:快速搭建稳定服务器,与小伙伴畅游游戏世界!
545 0
|
3天前
|
弹性计算 Ubuntu Windows
阿里云自建《幻兽帕鲁Palworld》多人游戏专属服务器,搭建方法分享
对于《幻兽帕鲁》的忠实粉丝来说,与好友一同在游戏中探险、生存无疑增加了更多的乐趣。而为了实现这一愿望,搭建一个专属的多人游戏服务器就显得尤为重要。今天,我将为大家带来一篇极简教程,教您如何在三次点击内,轻松搭建《幻兽帕鲁》的专属服务器。

热门文章

最新文章