新内容
今天介绍CMessage的实现, 下面就开始:
Message.cpp
#include
"
Message.h
"
#include
<
string
.h
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
CMessage::CMessage()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
this->Data = NULL;
this->Length = 0;
this->Time = 0;
this->Type = MT_INVALID;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
CMessage::CMessage(
char
*
msg,
int
len)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
this->Type = (MESSAGE_TYPE)msg[0]; //char* msg来自Net 第一个字节标识消息类型
this->Length = len;
this->Data = new char[len];
memcpy(this->Data, msg, this->Length);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
time(&this->Time); //记录消息时间
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
CMessage::
~
CMessage()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(this->Data != NULL)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
delete[] this->Data;
this->Data = NULL;
}
}
消息是由专门的CMessageDispatcher集中处理的,所以存在一个消息的队列
MessageQueue.h
#ifndef MESSAGEQUEUE_H_
#define
MESSAGEQUEUE_H_
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
"
Message.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
class
CMessageQueue
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
public:
CMessageQueue();
virtual ~CMessageQueue();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
int AddMessage(CMessage *msg); //将msg添加到消息队列中
int PopMessage(CMessage *msg); //将队列中最老的消息POP出来, msg为输出参数
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
private:
MESSAGE* _msgHead; //消息队列头指针, 每次就从此处POP消息
MESSAGE* _msgTail; //消息队列尾, 新加入的消息就接在这儿
int _msgCount; //队列中现有的消息
}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#endif
修改
和<一个简单的游戏(1)>中的CMessage不同, 修改为如下:
#ifndef MESSAGE_H_
#define
MESSAGE_H_
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
<
time.h
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
"
MessageType.h
"
#include
"
NetInfo.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
class
CMessage
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
public:
CMessage();
CMessage(char* szMsg, int len);
virtual ~CMessage();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
public:
time_t Time; //create time
MESSAGE_TYPE Type;
char* Data;
int Length;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
NET_INFO NetInfo; //此处为新增加, 包括消息来源ip和port
}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
struct
MESSAGE
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
CMessage *msg;
MESSAGE *next;
}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#endif
其中的NET_INFO定义如下:
NetInfo.h
#ifndef NETINFO_H_
#define
NETINFO_H_
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
struct
NET_INFO
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
unsigned long ip;
unsigned short port;
}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#endif
MessageType也作了修改
MessageType.h
#ifndef MESSAGETYPE_H_
#define
MESSAGETYPE_H_
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
enum
MESSAGE_TYPE //具体参看后文对现有各个消息数据的描述
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
MT_DAT = 0, //c <-> s
MT_TXT = 1, //c <-> s
MT_USR_ADD = 10, //c -> s
MT_USR_OUT = 11, //退出 c -> s
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
MT_SYS_STA = 20, //系统状态询问 s <-> c
MT_SYS_USR = 21, //s -> c : User Info
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
MT_INVALID = -1
}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#endif
消息格式
现在进展玩家连接服务器,玩家之间发送消息, 到此为止的消息格式如下:
char* msg[]
msg[0] : 消息类别, 最多0-127种消息,据此判断消息类别,进而进行不同的相应
msg[1-n] : 消息内容,不同消息种类不同
MT_TXT : c <-> s :
文本信息
msg[0] = MT_TXT
msg[1] = from id, -128 - 127,发送人的account id, 若为-1 则是系统信息
msg[2] = to id, -128 – 127, 当作为接收方时不等于自己的account id 则可以绝收; 否则必需指名, -1 为给所有人发消息
msg[3] = 消息有多长 0-255
msg[4-] = 消息内容
MT_USR_ADD : c <-> s : 登录
msg[0] = MT_USR_ADD
msg[1] = 名称长度 0-255
MT_USR_OUT : c -> s : 退出
msg[0] = MT_USR_OUT
MT_SYS_USR : s -> c : 其他用户信息
msg[0] = MT_SYS_USR
msg[1] = account id, 如果=-1, 说明登录失败
msg[2] = 名称长度, 0-255, 如果=0, 说明msg[1]是自己的account id
MT_SYS_STA : c <-> s : 链接状态保持
msg[0] = MT_SYS_STA
msg[1] = 服务器发送询问未得到应答的次数, 超过一定次数, 服务器将中止当前会话
所以每次收到这个消息, 需要尽快回复不带内容的MT_SYS_STA消息(msg[0]= MT_SYS_STA)
CMessage的作用
在整个游戏中,现在对CMessage的设想是这样的:
1.客户端和服务端的所有交互, 全部使用Message. 比如登陆,注册,发言,以及今后的游戏数据(比如角色状态)
2.服务端使用一个不限长度的(目前不限)队列存放待处理的消息
3.消息有多种类型和格式
4.消息使用UDP传输, 服务端可以广播消息
5.其实Message就是本游戏通信部分的内容载体
预告
<3>说明MessageQueue.cpp, 以及简单描述一下目前状态下相关对象的关系,这个设计的逻辑结构
<4>就主要说明dispatcher如何处理
<5>开始就设计网络连接了