采用c++的注释规范。
//表示注释一行,/**/表示注释范围中的所有代码。
void struct bool byte short int
double float long string vector
map key routekey module interface out
require optional false true enum const
所有标识符不能带有’tars_’符号,且必须以字母开头,同时不能和关键字冲突。
支持的基本类型包括以下:
void :只能在函数的返回值表示
bool :布尔类型,映射到 tars::Bool
byte :有符号字符,映射到 tars::Char
short :有符号短整型,映射到 tars::Short
int :有符号整型,映射到 tars::Int32
long :有符号长整型,映射到 tars::Int64
float :映射到 tars::Float
double:映射到 tars::Double
string:映射到 std::string,java:String
unsigned byte:无符号字符,c++映射到 unsigend char 其它版本 tars::Short
unsigned short:无符号短整形c++映射到 unsigned short 其它版本 tars::Int32
Unsigned int:无符号整形c++映射到 unsigned int其它版本 tars::Int64
枚举类型的定义如下:
enum TE
{
E1,
E2,
E3
};
说明:
Tars文件中可以定义常量,例如:
const int a = 0;
const string s = “abc”;
说明:
结构定义如下:
struct Test
{
0 require string s;
1 optional int i = 23;
};
key[Test, s, i];
说明:
key说明:
key详细说明:
其他说明:
序列用vector来定义,如下:
vector<int> vi;
字典用map来定义,如下:
map<int, string> m;
说明:
结构中可以定义数组类型,数组用[]来定义,如下:
byte m[5];
说明:
mLenvector<类型>byte m[5] 等价于定义vector<byte>:5结构中可以定义byte指针类型,指针用*来定义,如下:
byte *m;
指针类型使用时需要提前预分配内存块,指针需要内存时通过偏移指向预分配内存块,减少解码过程中的内存申请。
说明:
vector<类型>任何struct,map,vector都可以嵌套;
接口定义如下,例如:
interface Demo
{
int get(out vector<map<int, string>> v);
int set(vector<map<int, string>> v);
};
说明:
所有的struct,interface必须在名字空间中,例如:
module MemCache
{
struct Key
{
0 require string s;
};
struct Value
{
0 require string s;
};
interface MemCacheI
{
int get(Key k, out Value v);
int set(Key k, Value v);
};
};
说明:
每一个数据由两个部分组成,如下图:
| 头信息 | 实际数据 |
而其中头信息包括以下几个部分:
| Type(4 bits) | Tag 1(4 bits) | Tag 2(1 byte) |
Tag 2是可选的,当Tag的值不超过14时,只需要用Tag 1就可以表示;当Tag的值超过14而小于256时,Tag 1固定为15,而用Tag 2表示Tag的值。Tag不允许大于255。
Type表示类型,用4个二进制位表示,取值范围是0~15,用来标识该数据的类型。不同类型的数据,其后紧跟着的实际数据的长度和格式都是不一样的,详见一下的类型表。
Tag由Tag 1和Tag 2一起表示。取值范围是0~255,即该数据在结构中的字段ID,用来区分不同的字段。
注意,这里的类型与tars文件定义的类型是两个不同的概念,这里的类型只是标识数据存储的类型,而不是数据定义的类型。
| 取值 | 类型 | 备注 |
|---|---|---|
| 0 | int1 | 紧跟1个字节整型数据 |
| 1 | int2 | 紧跟2个字节整型数据 |
| 2 | int4 | 紧跟4个字节整型数据 |
| 3 | int8 | 紧跟8个字节整型数据 |
| 4 | float | 紧跟4个字节浮点型数据 |
| 5 | double | 紧跟8个字节浮点型数据 |
| 6 | String1 | 紧跟1个字节长度,再跟内容 |
| 7 | String4 | 紧跟4个字节长度,再跟内容 |
| 8 | Map | 紧跟一个整型数据表示Map的大小,再跟[key, value]对列表 |
| 9 | List | 紧跟一个整型数据表示List的大小,再跟元素列表 |
| 10 | 自定义结构开始 | 自定义结构开始标志 |
| 11 | 自定义结构结束 | 自定义结构结束标志,Tag为0 |
| 12 | 数字0 | 表示数字0,后面不跟数据 |
| 13 | SimpleList | 简单列表(目前用在byte数组),紧跟一个类型字段(目前只支持byte),紧跟一个整型数据表示长度,再跟byte数据 |
1.基本类型(包括int1、int2、int4、int8、float、double)
头信息后紧跟数值数据。char、bool也被看作整型。所有的整型数据之间不做区分,也就是说一个short的值可以赋值给一个int。
2.数字0
头信息后不跟数据,表示数值0。所有基本类型的0值都可以这样来表示。
这是考虑到数字0出现的概率比较大,所以单独提一个类型,以节省空间。
3.字符串(包括String1、String4)
String1跟一个字节的长度(该长度数据不包括头信息),接着紧跟内容。
String4与之类似。
4.Map
紧跟一个整形数据(包括头信息)表示Map的大小,然后紧跟[Key数据(Tag为0),Value数据(Tag为1)]对列表。
5.List
紧跟一个整形数据(包括头信息)表示List的大小,然后紧跟元素列表(Tag为0)
6.自定义结构开始
自定义结构开始标志,后面紧跟字段数据,字段按照tag升序顺序排列
7.自定义结构结束
自定义结构结束标志,Tag为0
对于自定义结构的持久化,由开始标志与结束标志来标识。
比如如下结构定义:
struct TestInfo
{
1 require int ii = 34;
2 optional string s = "abc";
};
struct TestInfo2
{
1 require TestInfo t;
2 require int a = 12345;
};
其中,默认的TestInfo2结构编码后结果为:

TUP底层协议完全采用Tars定义,与Tars的底层数据包定义一致,其中require的字段为TUP必须的字段,optional为访问Tars服务时额外需要用到的字段。
//请求包体
struct RequestPacket
{
1 require short iVersion; //版本号
2 optional byte cPacketType; //包类型
3 optional int iMessageType; //消息类型
4 require int iRequestId; //请求ID
5 require string sServantName; //servant名字
6 require string sFuncName; //函数名称
7 require vector<byte> sBuffer; //二进制buffer
8 optional int iTimeout; //超时时间(毫秒)
9 optional map<string, string> context; //业务上下文
10 optional map<string, string> status; //框架协议上下文
};
//响应包体
struct ResponsePacket
{
1 require short iVersion; //版本号
2 optional byte cPacketType; //包类型
3 require int iRequestId; //请求ID
4 optional int iMessageType; //消息类型
5 optional int iRet; //返回值
6 require vector<byte> sBuffer; //二进制流
7 optional map<string, string> status; //协议上下文
8 optional string sResultDesc; //结果描述
};
//返回值
const int TAFSERVERSUCCESS = 0; //服务器端处理成功
const int TAFSERVERDECODEERR = -1; //服务器端解码异常
const int TAFSERVERENCODEERR = -2; //服务器端编码异常
const int TAFSERVERNOFUNCERR = -3; //服务器端没有该函数
const int TAFSERVERNOSERVANTERR = -4; //服务器端没有该Servant对象
const int TAFSERVERRESETGRID = -5; //服务器端灰度状态不一致
const int TAFSERVERQUEUETIMEOUT = -6; //服务器队列超过限制
const int TAFASYNCCALLTIMEOUT = -7; //异步调用超时
const int TAFINVOKETIMEOUT = -7; //调用超时
const int TAFPROXYCONNECTERR = -8; //proxy链接异常
const int TAFSERVEROVERLOAD = -9; //服务器端超负载,超过队列长度
const int TAFADAPTERNULL = -10; //客户端选路为空,服务不存在或者所有服务down掉了
const int TAFINVOKEBYINVALIDESET = -11; //客户端按set规则调用非法
const int TAFCLIENTDECODEERR = -12; //客户端解码异常
const int TAFSERVERUNKNOWNERR = -99; //服务器端位置异常
(Notice: Origin official document is Here)