2014-08-26 20:06:24

  今天就是在开发这个EPOLL来处理网络事件 封装较为健壮的EPOLL模型来处理基本的网络IO

  1) 超时这个主题先没有弄

  在开发EPOLL包括select/poll类型io复用时,编程技术技巧分为几点:【下面都是针对与TCP协议 如果在以后开发中需要UDP会扩展这个编程技术】

1     要处理的文件描述符种类

  a)    listenfd=socket(); 这个listenfd 就是监听的listenfd  我们暂且把他作为一个总IO文件 其实这个listenfd就是一个数组索引。利用EPOLL监听的这个listenfd  READBLE状态,那么这里肯定需要放一个TCPAcceptHandler的函数来做相应的操作  因为监听到相应的核心东东就是一系列raw的客户端传来的信息:

其中有 ip  fd  port    作为一个功能完善的程序   ip  fd  port 这些作为raw信息 外加一系列RBL服务端所要控制的信息 构造了RBLClient的这个重量级数据结构,这样网络层和RBL服务层能够通过这个数据结构进行结合了。TCPAcceptHandler在目前看来就是做这个事情。

  b) 在a阶段构造了RBLClient 但是这个只是做了TCP的raw的ACCPET操作,但是需要引入真正的逻辑操作,也就是RBLServer接受到的所有的无论是自身的还是客户端的数据通信。 这里要利用typedef  void   FileProc(EpollEventLoop* ep,void *data,int fd) 给每一个来处理的文件的描述符注册一个通用的函数指针。这点内存消耗是必须的。这点暂时也不考虑了 这个阶段就是完成了注册事件。其实在这里需要处理可读和可写个事件 1) 可读是通过这层 交付给其他服务部分,2) 可写其他组建【自身】交给网络终端。

2   做成一个可以可随时插入的事件处理模型

  在实现上要像REDIS一样,随时可以插入事件  比如建立一个EPOLLLOOP对象之后,在后面的N个步骤之后 咱们插入一个listenfd到EPOLLLOOP对象里。

在或者 我处理完一个客户端命令我需要告诉他该怎么做 也是通过回调事件来完成。 同时由于客户端随时挂掉或者主动离开  需要做DEL功能。 这些看起来是显而易见 但是需要仔细封装好。【在REDIS中是注入了readQueryFromClient/  sendReplyToClient这2个事件函数】所以呢 嘿嘿 面对这么优秀的REDIS设计  我还是利用的模式  不过在哪里潜入这2个函数呢? 需要仔细的体会体会哦

另外定义一个什么样的协议呢? 兼容REDIS 我采用同样的协议模式。

简单的类定义如下:

class EpollEventLoop
{
public:
EpollEventLoop(int maxclient_):maxclient(maxclient_),maxepollevent(maxclient_),maxfd(-1)
{
epollfd=epoll_create(2048);
if(epollfd==-1)
std::cout<<"epoll create failed!"<<std::endl;
}
void CreatFileEvent(int fd,FileEvent* prere_event); //这里其实是注册事件
void DeleteFileEvent(int fd,int mask); //这里是删除事件
void ProcessEvents(int flag);//flag代表是那种类型的事件 在这里就是读写事件
~EpollEventLoop()
{
}
private:
int maxfd; //当前注册最大文件数目 eventloop初始化为-1
std::vector<FileEvent> fileevent; //文件事件 用std::vector存储
int epollfd; //epollfd文件描述符
std::vector<struct epoll_event> maxepollevent;
int maxclient;
};

  REDIS协议实现起来比较繁琐的是批处理操作:

  

  *<参数数量> CR LF
  $<参数 1 的字节数量> CR LF
  <参数 1 的数据> CR LF
  ...
  $<参数 N 的字节数量> CR LF
  <参数 N 的数据> CR LF
这样看来:传入上面总结的3个function(readQueryFromClient/  sendReplyToClient/TCPAcceptHandler)上都是以RBLClient做为主参数,解码或者加码都是在readQueryFromClient/  sendReplyToClient函数完成。
实现上还有一个难点:就是加码或者解码时这边传入的数据缓冲区不够怎么办?不能一下子放到结构化数据中,那就在实现时 做一个标记位,分多次读完 这样确实麻烦 这样在RBLClient就要多加几个结构来控制这些量了。 快哭了 网络协议部分http://www.redisdoc.com/en/latest/topic/protocol.html 就参考这个了 简化它 毕竟没有REDIS命令那么多 接下来是一个头痛的问题:上面的实现版本是单线程模式:
  接下来该怎么实现一个多线程呢?
  EPOLL线程:加入任务队列WorkQueue中, 是把什么加入到这个WorkQueue中呢? 其实就是把一个个RBLClient副本到WorkQueue中,而消费线程也就是调用TakeQueue()
形式化:
LOCK1()
TakeQUEUE()
UNLOCK1()
……
……
LOCK2()
CommandExecute()
UNLOCK2()

 对于LOCK1部分的实现  用无锁队列

 对于LOCK2 这里实现有一个CommandExecute() 这里就是控制一个部分bit数组 所以对我来讲 这个地方如果采用spin_lock() 加锁会不会好一一些呢? 这个需要评估

另外而言: 对于一致性而言,这样的操作模式 对于单客户可能不会马上得到想要的结果  这是一种必须的 是需要一个时间窗口  并非强一致性  我这里是牺牲了强一致性的 但是如果WorkQueue一直非常小的话 这个时间窗口肯定就非常小了 对应用程序造不成很大的影响。

明天的实现部分估计就是这个最难熬的线程控制部分了 这个部分计划用2到3天完成。明天把EventLoop代码实现的部分和协议实现部分先贴出来 然后串讲下思路
先这样了 bye
												

RBL开发笔记三的更多相关文章

  1. Django开发笔记三

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.基于类的方式重写登录:views.py: from ...

  2. RBL开发笔记一

    从这个系列开始  陆续记录整个RBL开发的过程   废话不多说   直入主题 10:54:53   2014-08-25 今天开发任务: RBL.h  的框架搭建出来   包括RBLServer RB ...

  3. RBL开发笔记二

     17:13:55 2014-08-25 有以下几个点:  第一 :怎么在预处理阶段能够做到识别某个宏是否给定义了  这里就定义了一个SystemConfig.h 专门做这个事情  当然是需要make ...

  4. Vue-cli开发笔记三----------引入外部插件

    (一)绝对路径直接引入: (1)主入口页面index.html中头部script标签引入: <script type="text/javascript" src=" ...

  5. 钉钉开发笔记(三)MySQL的配置

    最近在编写web的过程中,经常需要与后台工作人员互动.由于比较麻烦.没有效率. 就果断的请教了,公司的后台大牛,学习下数据库的一些简单操作,现在就把利用MySQL连接服务器, 进行可视化操作的简单步骤 ...

  6. openwrt开发笔记三:uci移植及API调用

    1.uci编译安装.移植 安装依赖 libubox #安装cmake sudo apt-get install cmake #下载依赖库libubox git clone http://git.nbd ...

  7. Django开发笔记六

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.登录功能完善 登录成功应该是重定向到首页,而不是转发 ...

  8. Django开发笔记五

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.页面继承 定义base.html: <!DOC ...

  9. Django开发笔记四

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.邮箱激活 users app下,models.py: ...

随机推荐

  1. ms sql 经典语句【珍藏】

    数据库中字段中有不需要"[演示数据请勿真实购买]" 例如: update Hishop_Products set ProductName = replace(ProductName ...

  2. java解析json与map,list相互之间的转换

    运行这个类需要加载jar包:ezmorph-1.0.6.jar.json-lib-2.4-jdk15.jar.jsoup-1.6.1.jar.commons-beanutils-1.8.0.jar.c ...

  3. jquery中,size()和length()方法有啥区别

    jquery中,size()和length()方法有啥区别? size()是jQuery提供的函数,而length是属性(不带括号). jQuery提供的源代码是这样的: size: function ...

  4. microstrip(微带线)、stripline(带状线) 指什么?

    带状线:走在内层(stripline/double stripline),埋在PCB内部的带状走线,如下图所示 蓝色部分是导体,绿色部分是PCB的绝缘电介质,stripline是嵌在两层导体之间的带状 ...

  5. Linux信号基础

    Linux信号基础   作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Linux进程基础一文中已经提到,Linux以进程为单位来 ...

  6. 《BI那点儿事》数据流转换——排序

    排序转换允许对数据流中的数据按照某一列进行排序.这是五个常用的转换之一.连接数据源打开编辑界面,编辑这种任务.不想设置为排序列的字段不要选中,默认情况下所有列都会选中.如图所示,按照TotalSuga ...

  7. AngularJS 特性—SinglePage、template、Controller

    单页Web应用(SinglePage) 顾名思义,只使用一个页面的Web应用程序.单页面应用是指用户通过浏览器加载独立的HTML页面,Ajax加载数据页面无刷新,实现操作各种操作. 模板(templa ...

  8. RSync实现文件备份同步详解

    1.rsync简介 rsync是Unix下的一款应用软件,它能同步更新两处计算机的文件与目录,并适当利用差分编码以减少数据传输.rsync中一项与其他大部分类似程序或协议中所未见的重要特性是镜像对每个 ...

  9. 0030 Linux 网络操作命令

    1. 主机是否可达 ping IP 2. 服务是否在运行 telnet IP port 3. 网络配置 ifconfig ip route arp 4. 网络访问 curl wget 5. 网络追踪 ...

  10. Mybatis 批量insert

    @Override public int insertHouseTypeScene(int htid, String name, String icon,int sort, List<House ...