`

由google protocol buffer想到协议序列化的一点简化

阅读更多

谷歌的PB协议很强大,主要是模拟了一个宿主语言,而C++原生语言对一些代码的动态生成是很弱势的。在游戏协议上,其实很多字段虽然有定义,但是都不一定每回发送的时候都使用到。如何的去灵活定制这里面的序列化?

 

因为谷歌是先用宿主语言描述了一遍,把字段和flag给绑定起来,然后生成代码。而在项目中,即使再强大的代码库,还是觉得很冗余。这里的冗余指的是说,从成本上考虑,一边是一个庞大的库,一边可以自己写个简单的但是稍微复杂的,虽然麻烦点,但是理解和维护成本肯定低于前者。

 

针对后者,我们来做一些定制序列化的分析:

肯定做不到谷歌那样根据单独一个flag变量动态的生成,那样代码越来越复杂;

写入的时候先记录写入变量的偏移位置,然后读的时候根据偏移位置自动读取?

似乎是个好主意,但是实施的时候,会发现光有个偏移位置还不够,读取的时候还要记录大小,那么结构就变成

【偏移量,2个字节】【字段大小,2个字节】【字段值】

也就是说把一个协议体的字段独立的拆开,但是容量上似乎不太合算,每个字段都要增加4个字节。


那么换种思路考虑,既然根据打FLAG无法做到很满意的效果,那能不能从代码上考虑?比如函数有read,write,我只要写一遍 write,保持写入的流顺序,解析的时候自动反解析出来即可。我觉得这样的成本可以接受。


那么继续分析现有的代码,

write(buffer,variable,sizeof(variable)),

read(buffer,variable,sizeof(variable)),


我们发现write和read的区别其实就是buffer到variable,或者variable到buffer。那么我们可以把这个函数给抽象出来,做成虚函数,分别实现相反的读写。然后上层对其进行封装,根据行为传入不同的参数:

 

class CIProtocolSerialLite
{
public:
	virtual char* Serial(char* pBuffer, char* pVariable, int nVariableSize)=0;

private:

public:

private:

};

class CProtocolSerialLiteSend:public CIProtocolSerialLite
{
public:	
	//pVariable拷贝到pBuffer
	virtual char* Serial(char* pBuffer, char* pVariable, int nVariableSize);

private:

public:

private:

};

class CProtocolSerialLiteRecv:public CIProtocolSerialLite
{
public:
	//pBuffer拷贝到pVariable
	virtual char* Serial(char* pBuffer, char* pVariable, int nVariableSize);

private:

public:

private:

};
 

 

 

/*
		CProtocolSerialLiteSend
*/
char* CProtocolSerialLiteSend::Serial(char* pBuffer, char* pVariable, int nVariableSize)
{
	memcpy(pBuffer, pVariable, nVariableSize);
	pBuffer+=nVariableSize;

	return pBuffer;
}

/*
		CProtocolSerialLiteRecv
*/
char* CProtocolSerialLiteRecv::Serial(char* pBuffer, char* pVariable, int nVariableSize)
{
	memcpy(pVariable, pBuffer, nVariableSize);
	pBuffer+=nVariableSize;

	return pBuffer;
}

 

 假如有这样一个协议体

 

#include "CProtocolSerialLite.h"

class CProtocolA
{
public:
	CProtocolA();
	bool Init();

	void Send(char* pBuffer);
	void Recv(char* pBuffer);

	int GetSize();
	void SetT1(int nValue);
	void SetT2(int nValue);
	void SetT3(int nValue);

private:
	void Serial(CIProtocolSerialLite *pSerialLite, char* pBuffer);

public:

private:
	int m_nSize;		//实际发送的大小

	//连续发送
	int m_nT1;
	int m_nT2;
	int m_nT3;

};

 

CProtocolA::CProtocolA()

 

{
	Init();
}

bool CProtocolA::Init()
{
	m_nSize = 0;
	//-1为无效值
	m_nT1 = -1;
	m_nT2 = -1;
	m_nT3 = -1;
	return true;
}

int CProtocolA::GetSize()
{
	return m_nSize;
}

void CProtocolA::SetT1(int nValue)
{
	m_nT1=nValue;
}
void CProtocolA::SetT2(int nValue)
{
	m_nT2=nValue;
}
void CProtocolA::SetT3(int nValue)
{
	m_nT3=nValue;
}

void CProtocolA::Send(char* pBuffer)
{
	CProtocolSerialLiteSend SerialLiteSend;
	Serial(&SerialLiteSend, pBuffer);
}

void CProtocolA::Recv(char* pBuffer)
{
	CProtocolSerialLiteRecv SerialLiteRecv;
	Serial(&SerialLiteRecv, pBuffer);
}


void CProtocolA::Serial(CIProtocolSerialLite *pSerialLite, char* pBuffer)
{
	pBuffer=pSerialLite->Serial(pBuffer, (char*)&m_nT1, sizeof(m_nT1));
	m_nSize += sizeof(m_nT1);

	pBuffer=pSerialLite->Serial(pBuffer, (char*)&m_nT2, sizeof(m_nT2));
	m_nSize += sizeof(m_nT2);

	pBuffer=pSerialLite->Serial(pBuffer, (char*)&m_nT3, sizeof(m_nT3));
	m_nSize += sizeof(m_nT3);

}

 

对外暴露的是send和write,接口可以根据具体的代码情况修改参数。并且在公共的Serial函数中,顺便把该协议真正的发送长度也求出来了,而且利用C++的指针也非常容易的插入到pBuffer中的任意位置(代码中无)。

 

如果只要修改Serial函数,那么之前的flag所带来的好处就完全可以抵消。至于选择性的字段那就很简单啦。自己实现个flag,在Serial函数里先写入flag, 剩下根据flag函数进行读取的代码都是一摸一样的

2
1
分享到:
评论

相关推荐

    Protocol Buffer

    1. **效率**:Protocol Buffer序列化后的数据比XML或JSON更紧凑,传输速度快,节省带宽。 2. **跨语言支持**:通过.proto文件,可以为多种编程语言生成对应的接口,方便多语言环境下的数据交换。 3. **版本兼容性*...

    Google protocol buffer 开发指南

    Google Protocol Buffer(简称Protobuf)是一种由Google开发的跨语言、跨平台的序列化框架,主要用于数据的序列化、反序列化,是一种更灵活、高效、自动化的机制。相比于XML等数据交换格式,Protocol Buffer具有更小...

    Google_Protocol_Buffer_的使用和原理

    Google Protocol Buffer 提供了一种高效的数据序列化方式,使得开发者能够在不同的语言和平台上轻松地交换数据。通过定义清晰的数据结构并在不同端之间共享这些定义,可以极大地简化数据交换的过程。此外,它的灵活...

    Python调用序列化数据工具Protocol Buffers——protobuf

    Protocol Buffers是Google开发的一种高效的数据序列化协议,它允许开发者将结构化的数据串行化,可用于数据存储、通信协议等方面。Python作为一门广泛使用的编程语言,可以方便地集成protobuf进行数据交换。在本文中...

    protocol buffer 3.0.0

    Protocol Buffer(简称protobuf)是Google开发的一种数据序列化协议,它是Google的一种高效、灵活且跨平台的数据交换格式。Protocol Buffers的设计目标是为了提供一种简单、快速、可扩展的方式来存储和传输结构化...

    Protocol_Buffer中文翻译

    Protocol_Buffer是一种强大的工具,用于通信协议和数据存储的结构化数据序列化。它提供了一种语言无关、平台无关且易于扩展的方法来处理复杂的数据结构。相比于XML等其他数据格式,Protocol_Buffer在数据大小、处理...

    数据交换格式-protocol buffer

    Protocol Buffer是Google开发的一种高效、灵活且跨平台的数据序列化协议,用于结构化数据的序列化,类似于XML、JSON,但更小、更快、更简单。它能够将结构化的数据序列化,可用于数据存储、通信协议等方面。Protocol...

    Apple 团队开源的基于 Google Protocol Buffer ("protobuf") 序列化技术的运行时库.zip

    Apple团队开源的基于Google Protocol Buffer("protobuf")序列化技术的运行时库是一个重要的软件开发资源,尤其对于使用Swift编程语言的开发者来说。Protocol Buffers是Google开发的一种高效的数据序列化协议,它...

    jersey和Google Protocol Buffer开发Demo

    【描述】:本示例将深入探讨如何使用Jersey,一个强大的Java RESTful Web服务框架,与Google Protocol Buffers(简称PB)结合,进行高效的数据序列化。这个Demo是实际开发中的一个实用案例,展示了这两个技术在实际...

    cocos2d-x protocol buffer android 工程

    Protocol Buffer(简称protobuf)是Google推出的一种数据序列化协议,它能够将结构化数据序列化,可用于数据存储、通信协议等方面。本项目结合了cocos2d-x与protobuf,旨在为Android平台的游戏开发提供高效的数据...

    protocol buffer编译器

    Protocol Buffer(简称protobuf)是Google开发的一种数据序列化协议,它是跨平台、语言无关的,用于高效地存储和传输结构化数据。protobuf的核心是.proto文件,这是一种定义数据结构的源代码格式,类似于XML或JSON,...

    protocol buffer已整合actionscript3输出

    Protocol Buffer是Google开发的一种数据序列化协议,它允许开发者定义数据结构,并将其高效地编码和解码为二进制格式,适用于跨平台、跨语言的数据交换。在本项目中,"protocol buffer已整合actionscript3输出"意味...

    ProtocolBuffer详细使用文档

    Protocol Buffers(简称 protobuf)是由 Google 开发的一种跨语言、跨平台的数据序列化机制。它不仅能够在保持原有数据格式不变的情况下灵活地更新数据结构,而且相较于 XML 和 JSON 等其他数据交换格式,具有更高的...

    使用Netty+Protocol Buffer实现聊天室

    Protocol Buffers是Google开源的一种数据序列化协议,类似于XML或JSON,但更紧凑、解析速度更快。它允许开发者定义数据结构,然后生成相应的代码,用于序列化和反序列化这些数据。在聊天室应用中,protobuf可以用于...

    Google Protocol Buffer 的使用和原理1

    Google Protocol Buffer(Protobuf)是一种高效、语言无关、平台无关的结构化数据序列化机制,由Google开发并广泛应用于数据存储和RPC(远程过程调用)系统。它的主要作用是将复杂的数据结构转化为二进制流,便于在...

    protocol buffers 官网中文教程

    Protocol Buffers是Google开发的一种数据序列化协议,用于结构化数据的序列化,可以视为一种跨平台、跨语言的数据交换格式。它允许开发者定义数据结构,然后生成代码以轻松地在各种数据流之间读写这些数据。Protocol...

    基于jquery mobile+websocket+protocol buffer的IM开发

    Protocol Buffer是Google开发的一种数据序列化协议,它可以将结构化数据编译成二进制格式,以便在网络中高效传输。相对于JSON或XML,Protocol Buffer具有更小的体积和更快的解析速度。在IM系统中,Protocol Buffer...

Global site tag (gtag.js) - Google Analytics