3d Game Walkman

3d图形渲染,网络引擎 — tonykee's Blog
随笔 - 45, 文章 - 0, 评论 - 309, 引用 - 0
数据加载中……

这段时间加入了网络序列化的功能

前面的文章也提到了,看了一些服务器的大师级的代码,SmartStruct和自定义序列化的方式都有,如果单单只用C结构体作为语意数据载体固然可以,但很多网友也提出了很多质疑,最大的缺陷就是灵活性欠佳,诚然如此。

这段时间沉下了心,好好写了一些类主要有:

ObjectStream
StreamBuffer
SerializeMap
PacketStruct
...

等等,有了前人的经验,似乎也算比较顺利,一个个从基本的数字,
到数组,到char[] (很多资料也称之为:raw 二进制序列)
再到STL 的一系列容器的序列化工作都实现了

其中大量使用了模版类的泛型设计,不必要求一个可序列化的类必须继承某某基类,只需要具备以下:

 SerializeTag ComputeTag();
 bool Read(ObjectStream& stream);
 bool Write(ObjectStream& stream);
 DWORD GetLength(ObjectStream& stream);
 bool operator==(const PacketHeader &other) const;

五个方法就可以了,如果随意给你一个事先定义好的类,可以实现序列化吗?当然可以,只需要写出该类的
Wrapped Proxy,再添加这5个方法,就能通过 ObjectStream 和 StreamBuffer 实现该类的序列化了

这些是写完成了,回头看看自己已经写好的网络逻辑模块,犯愁了。
唉……,加入序列化,相当于高层次的通讯协议全都变了,包结构要改,所有的业务逻辑通讯代码随之要改。

之前的工作…… 又要写大量的重构代码了。

重构真是件痛苦的事情。
最坏的打算把之前的一些逻辑东西按现有思路重写一遍嘛,二次加工也许能应祸得福,把破旧看不过眼的地方重整理的更漂亮,好比重新装修升级一样

现在,只能告诉自己一件事,沉下心,沉注气。

posted on 2008-03-01 17:15 李侃 阅读(1766) 评论(4)  编辑 收藏 引用 所属分类: 网络模块

评论

# re: 这段时间加入了网络序列化的功能  回复  更多评论   

不知道具体实现,应该只要基本的序列化机制即可,模板都可以不用,实现是不是复杂了点?
2008-03-01 22:42 | giscn

# re: 这段时间加入了网络序列化的功能  回复  更多评论   

具体实现就不发上来了,给你看一段测试的代码,模版的好处太多了

template <typename T>
void TestSerialize(T& val, bool enableTag)
{
ObjectStream s(enableTag);
StreamBuffer buf;
DWORD size = s.GetLength(val);
buf.realloc(size);

// write
assert( s.BeginWriting(&buf) );
assert( s.Write(val) );
assert( s.EndWriting() );

DumpBuffer(buf);

// read
T val_read;
assert( s.BeginReading(&buf) );
assert( s.Read(val_read) );
assert( s.EndReading() );

// nothing left to read
assert( buf.GetRestLength() == 0 );

// we read what we wrote
assert( val == val_read );
}

class Foo:public SerializeObject
{
public:
Foo(){
ZeroMemory(m_chr, 20);}

void Init(const std::string& s, const std::vector<DWORD>& v, DWORD d, const char * chr)
{
m_s = s;
m_v = v;
m_d = d;
strcpy(m_chr, chr);
}

bool operator==(const SerializeObject &other) const
{

return m_d == ((Foo&)other).m_d &&
m_v == ((Foo&)other).m_v &&
m_s == ((Foo&)other).m_s &&
strcmp(m_chr, ((Foo&)other).m_chr)==0;
}

SerializeTag ComputeTag()
{
return eTAG_USERCLASS;
}


bool Write(ObjectStream& stream)
{
return stream.Write(m_d) &&
stream.Write(m_s) &&
stream.Write(m_v) &&
stream.WriteRaw(m_chr, (DWORD) strlen(m_chr));
}

bool Read(ObjectStream& stream)
{
return stream.Read(m_d) &&
stream.Read(m_s) &&
stream.Read(m_v) &&
stream.ReadRaw((void *)m_chr);
}

DWORD GetLength(ObjectStream& stream)
{
return stream.GetLength(m_d) +
stream.GetLength(m_s) +
stream.GetLength(m_v) +
stream.GetRawLength((DWORD) strlen(m_chr));
}

public:
DWORD m_d;
std::string m_s;
std::vector<DWORD> m_v;
char m_chr[100];
};

void TestUserDefclass()
{
printf("test UserDefclass:\r\n");
printf("====================================\r\n");

printf("test User Def Class Foo with tags and no tags \r\n");
printf("---------------------------------\r\n");
Foo foo;
std::vector<DWORD> v;
v.push_back(1);
v.push_back(2);
char strs[20];
strcpy(strs, "jack");

foo.Init("hello", v, 3, strs);

TestSerialize(foo, true);
TestSerialize(foo, false);
}

void testSTL
{

printf("test std::set with tags and no tags \r\n");
printf("---------------------------------\r\n");
std::set<DWORD> st;
st.insert(9);
st.insert(11);
st.insert(10);
TestSerialize(st, true);
TestSerialize(st, false);
printf("\r\n");
}

ObjectStream 可以读和写任何类型的对象到StreamBuffer(StreamBuffer里面有个char[],二进制序列存这里)中去,这都归功于模版啊,
2008-03-02 13:21 | 李侃

# re: 这段时间加入了网络序列化的功能  回复  更多评论   

自己写的还是赞一个.

不过我喜欢用BOOST的序列化.

http://www.boost.org/libs/serialization/doc/index.html

2008-03-03 08:54 | 橙子

# re: 这段时间加入了网络序列化的功能  回复  更多评论   

恩,好像大家都这么说,有时间的话,我也去看看Boost的序列化的源码,看看有什么更好的可取之处
2008-03-06 16:47 | 李侃

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理