游戏服务器总是会与客户端通信的,一般通信协议是自定义的,比如下面这种
消息基类 用大、小消息号标志
struct MsgBase
{
MsgBase(UINT8 t,UINT8 st)
{
t_ = t;
st_ = st;
}
UINT8 t_;
UINT8 st_;
};
某个特定的消息具有约定好的 大、小消息号,只要双方保持一致即可,比如
UINT8 MSG_LOGIN= 1;
UINT8 MSG_ACCOUNT_PASSWD = 1;
struct UserAccountMsg : public MsgBase
{
UserAccountMsg() : MsgBase(MSG_LOGIN,MSG_ACCOUNT_PASSWD)
{
bzero(account,sizeof(account));
bzeor(passwd,sizeof(passwd))
}
char account[33];
char passwd[33];
};
这样做也是有问题的,字符串占的字节数比两个UINT8多很多啊,流量大大的浪费了。
那把字符串跟一个唯一ID绑定不就行了么,也省流量了,上面不就是这样做的么?
只不过上面是手动定义的形式,那有没有一个方法,能够自动把消息的类型名的字符串跟一个ID绑定呢?
把字符串跟ID绑定不是什么问题,生成一个唯一ID就够了,关键是怎么自动获取到消息类型的字符串表示呢?
c++里面是有一个宏可以获取到函数名,__function__,但是我们现在是要获取类型名呢?
想想,能不能通过函数名获取类型名呢?
想啊想。。。
类的构造函数名不是跟类型名是一样的么?哈哈
在类的构造函数里面使用__function__不就得到类型名了么,但是,你想在每个类里都手动加这么一句么。这也太挫了,咱程序员就是要偷懒的。
想想怎么自动完成吧。
那就只能在基类里面弄了,可是那样获取的是基类的类型名啊,不是子类的。
模板也可以把类型给传进来的。
template <typename T>
struct type_help_t
{
type_help_t()
{
name = __function__;
}
std::string name;
};
调用 type_help_t<UserAccountMsg>是不是可以呢?
发现不行,__function__不能获取到类型名,但是他的增强版__PRETTY_FUNCTION__倒是可以
他的调用结果是这么个形式
type_help_t<int> -> type_help_t<T>::type_help_t() [with T = int]
type_help_t<float> -> type_help_t<T>::type_help_t() [with T = float]
type_help_t<std::vector<int> > -> type_help_t<T>::type_help_t() [with T = std::vector<int, std::allocator<int> >]
写个宏吧 TYPE_NAME(x) type_help_t<x>::getInstance()->getName()
服务器启动的时候,把所有消息类型名跟ID绑定,这样client消息到来的时候就可以正确的分发到响应函数了,而且有一个好处,消息的ID可以每次启动服务器的时候都不一样,这样可以一定程度的防外挂,或者可以每个client每次连接上来的时候动态生成消息类型名与ID的映射,然后发到client,再来通信。