在服务器的网络层中,发送缓冲区是一个不可绕过的课题
目前我遇到了主要有两种处理方式
方式一:队列处理
1、在逻辑线程里面有一个总的发送队列,然后服务器每帧都会处理这个队列
2、每一个cLink里面有一个消息队列,当cLink的状态变化时候会去处理这个消息队列
3、在每一帧处理的时候
1 switch(pLink->m_eStat)2 {3 caseEF_IO_EAGAIN:4 pLink->m_send_q.push(msg);5 continue;6 break;7 caseEF_IO_NORMAL:8 {9 switch(send_message_process(&msg))10 {11 caseEF_EVR_TX_EAGAIN:12 {13 pLink->m_send_q.push(msg);14 pLink->m_eStat =EF_IO_EAGAIN;15
16 uint32 type = EF_EVT_READ |EF_EVT_WRITE;17 ModIoHandle(pLink->_fd, pLink->_sn, type);18
19 //cout << "mod_io_handler " << pLink->_fd << ":" << pLink->_sn << " " << type << endl;
20 }21 break;
如果该链接状态可以发送则直接发送出去,否则该消息从总的消息队列转移到了cLink的消息队列,
4、在epoll中,当cLink的网络状态转换为可发送时候,再针对每一个cLink的发送队列进行处理,发送消息
优点:
处理方式简单,处理流程清晰明了
缺点:
因为每一个队列里面都是一个消息包,发送的时候,每一个包发送一次,调用一次send(),可能会造成太多小包的发送
方式二:总的缓冲区处理
1、不使用队列,而是维护自定义的一个消息缓冲区 cSendMsg
1、每一次都把消息先放进消息缓冲区,自己缓冲内存,缓冲大小可扩展(有最大值限制)
2、每一次发送的时候把缓冲区的内容取出,整块内存发送
缺点:
维护这个缓冲区需要自己处理,容易出错
优点:
可以避免多次发送小包,可以多个消息包作为一个打包一起发送,提高IO效率
static const uint32 DEFAUTL_BUFFER = 1024 * 40; //10k
class CEncrypt;
static const uint32 c_wMaxSendMsg = 5120000;
class cSendMsg
{
public:
~cSendMsg();
cSendMsg(uint32 sz = DEFAUTL_BUFFER);
bool AddMsg(const void* pMsg, uint32 nSize);
bool AddQueueMsg(const char* pBuf, uint32 nSize);
bool Init(uint32 sz);
bool Release();
bool AddBuffer(const void* pMsg, uint32 sz);
bool AddQueueBuffer(const char* pBuf, uint32 sz);
bool AddQueueBufferFront(const char* pBuf, uint32 sz);
bool AddQueueMsgFront(const char* pBuf, uint32 nSize);
//bool AddQueueBufferA(const char* pBuf, uint32 nSize);
bool DoubleBuf(uint32 dwSize = 0);
void ResetBuf();
void ResetBufLen(uint32 nLen, uint32 off);
const char* GetGroupBuffer(uint32& nLen, uint32& off) const;
const char* GetQueueBuffer(uint32& nLen, uint32& off) const;
uint