二进制协议 vs 文本协议
在服务器程序开发过程中,各个服务直接需要进行交互。这样就需要定义消息的协议,一般来说协议主要包括二进制协议和文本协议,下面就我在工作中用到的两种协议说说自己的看法。
1 二进制协议
目前在公司做服务器后台开发的工作,需要多个服务程序进行交互。因为是TCP直连,所以直接采用二进制消息的方式。消息的定义统一采用消息头(消息ID+消息长度)+x消息体(消息内容)的方式,所以扩展是比较方便的。用代码表示如下
struct CommonMsg
{
uint32_t m_msgId;
uint32_t m_msgLen;
};
struct KeepAlive:public CommonMsg
{
uint32_t m_timeStamp;
};
doRead()
{
CommonMsg * msg=(CommonMsg*)buffer;
if(msg->m_msgId==ID_KEEP_ALIVE)
{
handleKeepAlive(msg);
}
}
1.1 优点
二进制协议有以下几个优点:
1. 节约内存,带宽。
二进制协议只保存了必须的信息,在需要传递大量信息的时候,对于带宽的节省是非常明显的。
2. 方便加密。
二进制协议很方便使用异或 或者压缩的方式进行加密,防止协议被破解,从而保护了传递的信息,增加协议破解的难度。
1.2 缺点
二进制协议的缺点也非常明显:
1. 难以解析。
对于每一条消息,因为无法自解释,所以对于每一条消息都必须要有对应的文档进行说明。文档和代码的一致性就显得很重要了。
2. 不跨处理器。
因为是严格的内存到对象的转换,所以要求发送方与接收方的的机器字节序保持一致,否则无法正确解析。
3. 不方便消息的修改。
对于消息的扩展是比较方便的,不过也只能在消息的后面添加字段,才能做到兼容。如果修改已有字段的顺序就会造成消息无法正确解析。
2 文本协议
在http请求中,一般会采用json或者xml形式的协议。特别是对于web端的前后台交互更多的会采用json。
用代码表示一般如下:
//http://www.chat.com/getuserinfo/
//Request:
{
"user":"1234@qq.com",
"token":"af89da025"
}
//Response
{
"code":0,
"msg":"succeed",
"info":
{
"user":"1234@qq.com",
"name":"test",
"group":"test",
"tel":"18888888"
}
}
2.1
文本协议有以下优点:
1. 扩展方便。
如果需要增加一些条件,直接添加Key和Value就可以了,扩展方便。
2. 方便升级。
如果原有的消息需要升级,可以在回复里直接给出升级后请求的地址和消息格式。
3. 方便跨语言跨平台。
对于消息的发送方和接收方的采用的编程语言没有严格的限制,对于多语言编写提供了便利。
2.2
文本协议的有以下缺点。
1. 浪费带宽。
因为文本协议传递了太多的不会在处理中实际使用的内容,所以在如果处理的请求的量非常大的话,对于带宽的浪费很严重。
2. 不方便加密。
因为文本协议方便解读,所以如果不希望跟其他的程序共享通信协议,就最好不要采用文本协议。
3 应用场景
尺有所短,寸有所长。每种协议都有自己适用场景。
- 对于公司内部的服务程序之间进行通信,采用二进制协议好一些。
- 对于需要提供给外部的接口,提供文本格式的协议更好。