面向接口的网络处理模型(封装select, epoll, poll)

天上午很不幸碰到一个select的问题,幸好以前对网络I/O处理的模块进行了封装,今天下午很快就完成了一个基于poll的I/O处理封装,
 
只需要进行1行代码的替换,就可以轻松从select架构转换到poll,同理也可以转换到epoll。
 
自己可以随心所欲的切换网络I/O处理架构!!!
 
这里是接口,使用的是模板,这里没有使用C++的继承,有如下几点考虑:
 
(1) 效率, 模板实现的多态是发生在编译的时候,而继承重载虚函数是通过程序运行的时候,根据vtable指针对函数的实际地址进行寻址,
 
            当然比模板慢, 而且还可能会增加4字节的vptr指针
 
(2) 面向接口编程: 继承一般是有实际的逻辑含义的对象的使用,比如人,黑人之间。
 
                而我们的网络处理模型,只是不同的处理方法,所以用模板更好一些
 
 
 
 
下面的代码请放到一个头文件中,不然存在编译问题,详情请见<<C++templates>>第6章
 
这里对fd的访问采用的是迭代模式,必须先启动开始迭代,让后才能依次迭代。
 
具体的网络模型对fd存放形式对于调用者是不可见的, 只能获取迭代指针,访问网络模型的内部fd列表。
 
各个实现类内存的数据结构自己是可以优化的,目前是全部采用数组
 
template <class T>
class InterfaceIOQuery
{
 private:
 
  T member;
 
 public:
 
  //添加一个关心的fd
  void remove(int* pFd, int iOption);
 
  //测试该fd是否可读
  bool isCanRead(int* pIterator);
   
  //测试该fd是否可写
  bool isCanWrite(int* pIterator);
 
  //测试该fd是否异常
  bool isExcept(int* pIterator);
 
  //设置关心的事件
  void setQueryOption(int iOption); 
 
  //注册一个fd
  void registerFd(int pFd, int iOption);
 
  //轮询操作, -1 永久等待, 0轮询,  >0, 按时间轮询
  int selectWithTime(int iTime);
 
  //开始遍历fd列表
  int* getSelectFdBegin();
 
    //取得下一个fd的指针
   int* getSelectFdNext();
 
};
 
 
 
 
具体的select 和poll, 接口的实现请见附件,
 
使用的范例代码如下:
//设置关心的事件
m_selector.setQueryOption(OP_READ);
//注册fd和该fd关心的事件
m_selector.registerFd(m_workPipeFd[0], OP_READ);
 
 int iReady;
 
 for ( ; ; )
 {
  //进行select操作
  iReady = m_selector.selectWithTime(-1);
 
  if (iReady < 0)
  {
   throw CException(errno);
  }
  else if (iReady == 0)
  {
   m_log.writeLog(LOG_INFO, "doSelect()", "work%d do select with 1 second time out", m_iThreadID);
  }
  else
  {
    //开始迭代访问
   m_selector.getSelectFdBegin();
 
   int* iterator;
   
    //为NULL标识访问完毕
   while (NULL != (iterator = m_selector.getSelectFdNext()))
     
   {
    if (m_selector.isCanRead(iterator))
    {
     if (*iterator == m_workPipeFd[0])
     {
      int iRecive;
      int iRead = r_read(*iterator, (void*)(&iRecive), sizeof(iRecive));
 
      if (iRead <= 0)
      {
       m_log.writeLog(LOG_ERR, "doSelect()", "work%d read pipe %d fail ", m_iThreadID, *iterator);
      }
      else
      {
       m_log.writeLog(LOG_INFO, "doSelect()", "work%d recevie fd %d success ", m_iThreadID, iRecive);
       m_selector.registerFd(iRecive, OP_READ);
      }
      
     }
     else
     {
      replayToClient(iterator);
     }
     
     --iReady;
 
     if (0 == iReady)
     {
      break;
     }
    }
   }
  }
 }
  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值