服务器设计笔记(1)-----消息的封装

    消息的封装方式有多中,比如xml,json等,但是我依然觉得使用拼数据的方式最简单,也最节省带宽。比如我们处理一个逻辑就可以这样处理了:

    int cast_net(MessageBlock &mb)

    {

        int  area_id,lvl;

        mv >> area >> lvl;

        //逻辑处理

        //....

        MessageBlock re_mb;

        re_mb << item_id << item_sum;

        return this->respond_to_client(re_mb); 

    } 

    

    在之前公司的时候,使用的是ace的ACE_Message_Block,来到了新的公司,重新封装了ACE_Message_Block。 很多地方学习了ACE的设计。比如 wr_ptr(),rd_ptr()等。 

    MessageBlock.h 文件

    /*

* MessageBlock.h
 *
 *  Created on: Aug 11, 2012
 *      Author: archy_yu
 */

#ifndef MESSAGEBLOCK_H_
#define MESSAGEBLOCK_H_

#include <TlvPackage.h>
#include <string>

class MessageBlock
{
public:
    MessageBlock(int =0);
    /*
    MessageBlock(short tag,short len);
    MessageBlock(TLVEntity paraTlvEntity);
    */

    MessageBlock(MessageBlock &mb);

    /*
    MessageBlock(char* msg,int len);
    MessageBlock(std::string str);
    */
    virtual ~MessageBlock();

    MessageBlock& operator << (const char &value);
    MessageBlock& operator << (const short &value);
    MessageBlock& operator << (const int &value);
    MessageBlock& operator << (const char* ss);

    MessageBlock& operator >> (char &value);
    MessageBlock& operator >> (short &value);
    MessageBlock& operator >> (int &value);
    MessageBlock& operator >> (char* ss);

    void set_len();
    int get_len();
    char* wr_ptr();
    char* rd_ptr();
    int Capacity();

private:
    int wr_position;
    int rd_position;
    int capacity;
    int len;
    char* data;
};
#endif /* MESSAGEBLOCK_H_ */

MessageBlock.cpp文件

/*
 * MessageBlock.cpp
 *
 *  Created on: Aug 11, 2012
 *      Author: archy_yu
 */

#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "MessageBlock.h"

MessageBlock::MessageBlock(int n)
{
    wr_position = 0;
    rd_position = 0;
    len = 0;
    this->data = (char *)calloc(n > 0 ? n : 1024,sizeof(char));
    this->capacity = n > 0 ? n : 1024;
}

/*
MessageBlock::MessageBlock(short tag,short len)
{
    this->dataindex = 0;
    this->len = len;
    this->data = (char *)calloc(len,sizeof(char));
    if(this->data == NULL)
    {
        //error
    }
}

MessageBlock::MessageBlock(TLVEntity paraTlvEntity)
{
    this->dataindex = 0;
    this->len = paraTlvEntity.Length;
    this->data = (char* )calloc(paraTlvEntity.Length,sizeof(char));
    if(this->data == NULL)
    {
        //error
    }
    memcpy(this->data,paraTlvEntity.Value,paraTlvEntity.Length);
}
*/
MessageBlock::MessageBlock(MessageBlock &mb)
{
    this->data = mb.data;
    this->len = mb.len;
    this->capacity = mb.capacity;
    this->rd_position = mb.rd_position;
    this->wr_position = mb.wr_position;
}

/*
MessageBlock::MessageBlock(char* msg,int len)
{
    this->data = (msg);
    this->len = len;
    this->dataindex = 0;
}

MessageBlock::MessageBlock(std::string str)
{
    this->data = const_cast<char* >(str.c_str());
    this->len = str.size();
    this->dataindex = 0;
}
*/
MessageBlock::~MessageBlock()
{
    // TODO Auto-generated destructor stub
    free(this->data);
}

MessageBlock& MessageBlock::operator << (const char &value)
{
    if((wr_position + sizeof(char)) > this->capacity)
    {
        this->data = (char* )realloc(this->data,wr_position + sizeof(char));

        if(this->data == NULL)
        {
            return *this;
        }
        this->capacity = this->wr_position + sizeof(char);
    }

    *((char* )(this->data + wr_position )) = value;
    wr_position += sizeof(char);
    len = wr_position ;

    return *this;
}

MessageBlock& MessageBlock::operator <<(const short &value)
{
    if((wr_position + sizeof(short)) > this->len)
    {
        this->data = (char* )realloc(this->data,wr_position + sizeof(short));
        if(this->data == NULL)
        {
            return *this;
        }
        this->capacity = this->wr_position + sizeof(short);
    }

    *((short* )( this->data + wr_position )) = value;
    wr_position += sizeof(short);
    len = wr_position;

    return *this;
}

MessageBlock& MessageBlock::operator <<(const int &value)
{
    if((wr_position + sizeof(int)) > this->len)
    {
        this->data = (char *)realloc(this->data,wr_position + sizeof(int));
        if(this->data == NULL)
        {
            return *this;
        }
        this->capacity  = this->wr_position + sizeof(int);
    }

    *((int* )( this->data + wr_position )) = value;
    wr_position += sizeof(int);
    this->len = wr_position;

    return *this;
}

MessageBlock& MessageBlock::operator <<(const char* ss)
{

    short len = strlen(ss);

    if((wr_position + 2 + len) > this->len)
    {
        this->data = (char *)realloc(this->data,wr_position + 2 + strlen(ss));
        if(this->data == NULL)
        {
            return *this;
        }
        this->capacity = this->wr_position + 2 + strlen(ss);
    }

    *((short* )(this->data + wr_position)) = len;
    wr_position += sizeof(len);
    this->len = wr_position;

    memcpy(this->data + wr_position,ss,len);
    wr_position += len;
    this->len = wr_position;
    return *this;
}

MessageBlock& MessageBlock::operator >>(char &value)
{
    if((rd_position + sizeof(char)) > this->len)
    {
        return *this;
    }

    value = *((char* )(this->data + rd_position ));
    rd_position += sizeof(char);

    return *this;
}

MessageBlock& MessageBlock::operator >>(short &value)
{
    if((rd_position + sizeof(short)) > this->len)
    {
        return *this;
    }

    value = *((short* )(this->data + rd_position ));
    rd_position += sizeof(short);

    return *this;
}

MessageBlock& MessageBlock::operator >>(int &value)
{
    if((rd_position + sizeof(short)) > this->len)
    {
        return *this;
    }
    value = *((int* )(this->data + rd_position));
    rd_position += sizeof(int);
    return *this;
}

MessageBlock& MessageBlock::operator >>(char* ss)
{
    short len = *((short* )(this->data + rd_position));

    if( (this->rd_position + sizeof(len) + len) > (this->len) )
    {
        return *this;
    }

    rd_position += sizeof(len);
    memcpy(ss,this->data + rd_position,len);
    ss[len] = '\0';
    rd_position += len;
    return *this;
}

char* MessageBlock::wr_ptr()
{
    return this->data + wr_position;
}

char* MessageBlock::rd_ptr()
{
    return this->data + rd_position;
}

int MessageBlock::Capacity()
{
    return this->capacity;
}

void MessageBlock::set_len()
{
    (*(short *)(this->data)) = this->wr_position;
}

int MessageBlock::get_len()
{
    return this->len;}

   需要说明的几点: 

    1. linux服务器一般都是小端的设计,但是flash在使用ByteArray的时候就要注意大端小端的使用了。 

    2. 这样的类不是一次能设计好的,需要在后续的开发过程中持续的改进。  

时间: 2024-10-29 18:43:07

服务器设计笔记(1)-----消息的封装的相关文章

服务器设计笔记(3)-----消息队列

    摘抄的一篇文章,故拿出来记录下,下篇博客把解决代码分享出来.感谢这篇文章的原作者,解决了棘手的问题.       我们所能想到的最简单的消息队列可能就是使用stl的list来实现了,即消息队列内部维护一个list和一个互斥锁,putMessage时将message加入到队列尾,getMessage时从队列头取一个message返回,同时在getMessage和putMessage之前都要求先获取锁资源. 实现虽然简单,但功能是绝对满足需求的,只是性能上可能稍稍有些不尽如人意.其最大的问题

服务器设计笔记(4)-----客户端通信模块

   整个底层通信模块修改过很多次,因为首次使用epoll,在其中遇见了很多问题,最终设计成下面的方式:        1: 对于epoll中EPOLLOUT事件的使用,因为频繁的调用send()函数,系统会在内核模式和用户模式之间切换太多消耗太大,所以最终启用了定时器模式,比如以50ms为间隔,定时的遍历所有的ClientPlayer 去发送 OutStream 里面的数据.    2: 最开始使用玩家的id 对应每个玩家的ClientPlayer的,在玩家没有进入的时候 使用玩家的账号名:

服务器设计笔记(1)-----定时器的实现(C++)

很久之前听著名页游服务器主程讲座时,讲到过定时器的实现,基本思路如下(易语言)        while(true)        {              对定时器进行排序.              for(遍历定时器)              {                    if 如果定时器到:                           callback;                    else                            bre

服务器设计笔记(2)-----定时器的实现(C++)

   很久之前听著名页游服务器主程讲座时,讲到过定时器的实现,基本思路如下(易语言)        while(true)        {              对定时器进行排序.              for(遍历定时器)              {                    if 如果定时器到:                           callback;                    else                           

服务器设计笔记(5)-----守护进程

守护进程的定义:        通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.这事百科对此的解释,在游戏服务器里面也有守护进程,特点大概也类似. 游戏守护进程的定义:        游戏服务器里面的守护进程大概完成的职责有这些.1,负责多个进程的启动:2,在进程挂掉的时候负责启动相应的进程:3,可以查询程序运行的情况等等. 游戏守护进程的原理:       设计守护进程为父进程,验证进程,聊天

服务器设计笔记(5)-----分享几个线程安全的容器

    首先是 队列 PipeList    /* * PipeList.h * * Created on: Aug 28, 2012 * Author: archy_yu */ #ifndef PIPELIST_H_ #define PIPELIST_H_ #include <list> #include "Mutex.h" #include "GameUtil.h" template <class CObject> class PipeL

动态网页设计笔记

动态网页设计笔记    JavaScript.ASP.ASP.Net.JSP笔记   JavaScript ASP.net ASP 1.基本控件的使用6.客户端脚本的基本对象    ***41.常用的Javascript内建类的方法  ***2.让TextArea自动换行3.让TextArea支持Table键4.复制数据到剪贴板5.得到当前选中的文本7.保护自己编写的HTML和脚本的方法8.IE地址栏前换成自己的图标9.可以在收藏夹中显示出你的图标10.关闭输入法11.直接查看源代码12.在Ja

ios-iOS使用AsycSocket第三方库与服务器连接,怎样接收服务器的推送消息?

问题描述 iOS使用AsycSocket第三方库与服务器连接,怎样接收服务器的推送消息? iOS开发使用AsycSocket第三方库,长链接, 那么为什么收不到服务器的推送消息? 解决方案 应该不是 APNS ,不是苹果的推送业务, 如果是的话,那么我们用的QQ,两个用户进行聊天的时候,不可能每一个聊天信息都要经过苹果服务器那边的呀 解决方案二: APNS你app搭建好了么? 解决方案三: //设置读取超时 -1 表示不会使用超时 #define READ_TIME_OUT -1 #define

netty 转发消息-netty服务器如何转发客户端消息?

问题描述 netty服务器如何转发客户端消息? 我用map保存客户端的channel,遍历map --> channel.writeAndFlush(**),客户端收不到啊 哪里出了问题吗 还是思路错了 解决方案 http://www.oschina.net/question/156914_220771