本期简介
开发前置工作:安装配置protocolbuffers工具。
【protocolbuffer是什么?】
简单理解就是:
谷歌公司开发的一款比json、xml压缩还要小,网络传输还要快,已经实现序列化的通信信息工具。
(因为比json有更多的压缩,因此压缩结果也失去了可读性。)
主要工作
protocolbuffers官网
developers.google.cn/protocol-buffers
上面有csharp的zip但是需要编译。
下载的最新版本3.19的win64.zip可以直接安装。
配置环境
安装好之后再PATH中添加安装位置(bin目录)
配置好后检验是否配置成功
打开命令行,输入protoc --version
如果识别了protoc指令并且显示了版本信息就可以开始使用了。
编写proto文件
创建一个记事本文件,修改文件后缀为“.proto”。
可以使用VsCode等编辑器软件,编辑更方便高效。
语法上其实和json挺像的。
关键字或者其他具体的语法可以参考官网。
在这里列出本项目proto文件编写时的前两行文本:
//这是指定此proto文件使用proto3语法,3和2语法有区别,需要注意一下
syntax = "proto3";
//下面是指定包名或者命名空间,C#中想要使用编译出来的内容,需要`using SocketGameProtocol;`
//当然这个名字是自己起的。
package SocketGameProtocol;
//其他规定语句见官方文档吧。
//可以在proto文本中写注释
本文以C#写服务端。但其实proto文本本身不会有区分,仅仅是通过protoc指令编译所写的proto文件时会自动生成所需要语言的代码。(见后文的编译proto文件)
此项目的proto文件放在文末。
编译proto文件
命令行中使用protoc指令,protoc --help
会列出帮助菜单。
下面列出编译指令。
protoc --csharp_out ./ --proto_path=./ 要编辑的文件(带后缀)
此条指令
第一个参数--csharp_out
是编译为.cs(C#)脚本。这也是上文中提到的,可以编译为需要的语言。而proto文件内部对于不同语言是没有区分的。
如果要java,那么应该换为--java_out。
此参数后面需要一个空格
,然后跟上要输出的路径。
./
代表输出到当前文件夹。(相对路径的写法)
第二个参数--proto_path
是要编译的文件路径。也就是你要编译你刚写的那个proto文件。
紧跟一个=
+路径。此条指令的意思是在当前文件夹中找到要编译的文件。所以能成功编译的前提是cmd目录已经切换到proto文件所在的地方。
“./”之后需要跟一个空格!!!!
,然后写上文件名要带后缀。
下面举个使用例子
目录结构:
cmd指令:(第一次的报错了是因为指令参数只打了一个“-”,需要两个“-”)
成功之后可以看到生成了.cs文件。
总结
本篇记录protocolbuffer的安装配置与使用,记录了项目的proto文件。
但是使用protocolbuffer并不会解决TCP粘包机制。
对于粘包机制的解决方案请见下一篇。
编译出来如何使用的,代码将会在后续博文中写明。
项目proto文件内容
syntax = "proto3";
package SocketGameProtocol;
//要执行何种请求
enum RequestCode {
RequestNone = 0;
//用户
UserRequest = 1;
//公告
NoticeRequest = 2;
//游戏战绩
GameRequest = 3;
}
//这个请求要干什么,对应什么事情
enum ActionCode {
ActionNone = 0;
//注册
Register = 1;
//登录
Login = 2;
//获取公告
ReceiveNotice = 3;
//记录战绩
SaveRecord = 4;
//查询个人信息
CheckMyInfo = 5;
//查询排行榜
CheckRank = 6;
//查询游戏信息
CheckMyGameInfo=7;
}
//请求结果,服务端返回给客户端时需要定义ReturnCode。
enum ReturnCode {
ReturnNone = 0;
//成功
Succeed = 1;
//失败
Fail = 2;
//可以多写几个,比如注册时用户名已存在可以精确地返回:HaveExist
//不然客户端只知道是失败,但是不知道到底因为什么。总之按需写即可
//HaveExist = 3;
}
//哪个游戏
enum GameId
{
PlatformGame = 0;
RacingGame = 1;
PveGame = 2;
AsteroidGame = 3;
FPSGame = 4;
}
//socket传输消息的总包
message MainPack {//对应着MainPack
RequestCode requestCode = 1;
ActionCode actionCode = 2;
ReturnCode returnCode = 3;
LoginPack loginPack = 4;
NoticePack noticePack = 5;
RecordPack recordPack = 6;
RankingPack rankingPack=7;
}
//登录注册包
message LoginPack {
//账号
string account = 1;
//密码
string password = 2;
//昵称
string username = 3;
//时间//用于查信息
string regTime = 4;
}
message NoticePack//公告,比较简略
{
string content = 1;
}
message RecordPack//战绩包
{
GameId gameId = 1;
bool isWinner = 2;
int32 score = 3;
int32 winNum=4;
int32 allNum=5;
}
message RankingPack//排行榜查询包
{
GameId gameId=1;
//repeated是关键字---可重复,相当于数组/列表
repeated ScoreInfo scoreInfo=2;
}
message ScoreInfo//记录一条排行榜信息
{
string username=1;
int32 score=2;
}