sock_ev——linux平台socket事件框架(event loop)

本文介绍了如何通过封装事件监听方式,实现客户端的统一管理,并详细阐述了EventLoop的设计与实现过程,包括初始化、添加事件、移除事件以及监听事件触发等关键功能。

上一篇我们封装了三种事件监听方式,如果分别提供给客户端使用,有点不方便,也不利于统一管理;我们再封装一层EventLoop。

/***************************************************************************************
****************************************************************************************
* FILE		: event_loop.h
* Description	: 
*			  
* Copyright (c) 2012 by Liu Yanyun(E-mail:liuyun827@foxmail.com). All Rights Reserved.
*            Without permission, shall not be used for any commercial purpose
* 
* History:
* Version		Name       		Date			Description
   0.1		Liu Yanyun		2012/12/20		Initial Version
   
****************************************************************************************
****************************************************************************************/


#ifndef _EVENT_LOOP_H_
#define _EVENT_LOOP_H_

#include <string.h>
#include <stdint.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <poll.h>
#include "sock_ev.h"

class Socket;
class EventDispatcher;


/*==================================================================
* Function	: EventLoop
* Description	: event loop,it is adapter for select poll epoll wait event
==================================================================*/
class EventLoop
{
public:

  /*==================================================================
  * Function	: EventLoop.EventLoop
  * Description	: construction function
  ==================================================================*/
  EventLoop();

  /*==================================================================
  * Function	: EventLoop.~EventLoop
  * Description	: Destructor function
  ==================================================================*/
  virtual ~EventLoop();

  /*==================================================================
  * Function	: EventLoop.initialize
  * Description	: initialize the loop
  * Input Para	: type_--dispatcher type
  * Return Value: success return true,or else return false
  ==================================================================*/
  bool initialize(LoopType type_);

  /*==================================================================
  * Function	: EventLoop.addEvt
  * Description	: add an event and register callback
  * Input Para	: 
  * Output Para	: 
  * Return Value: success return true,or else return false
  ==================================================================*/
  bool addEvt(Socket *sock_,
      EvCallBack cb_,
      EventType evt_,
      void *arg_);

  /*==================================================================
  * Function	: EventLoop.removeEvt
  * Description	: remove an event and un-register callback
  * Input Para	: 
  * Output Para	: 
  * Return Value: success return true,or else return false
  ==================================================================*/
  bool removeEvt(Socket *sock_,
      EventType evt_);

  /*==================================================================
  * Function	: EventLoop.listen
  * Description	: wait for event trigger
  * Input Para	: 
  * Output Para	: 
  * Return Value: 
  ==================================================================*/
  int listen(int timeout_);
      
private:

    EventDispatcher *dispatcher;
    SockMapT  sockMap;
};

#endif /*_EVENT_LOOP_H_*/


 

#include "event_loop.h"
#include "sock_ev.h"
#include "event_dispatcher.h"
#include "socket_base.h"
#include "socket.h"


EventLoop::EventLoop()
{
  dispatcher = NULL;
}
EventLoop::~EventLoop()
{
  if(NULL != dispatcher) delete dispatcher;

  sockMap.clear();
}
bool EventLoop::initialize(LoopType type_)
{
  if(selectLoop == type_)
  {
    dispatcher = new SelectDispatcher();
  }
  else if(pollLoop == type_)
  {
    dispatcher = new PollDispatcher();
  }
  else if(epollLoop == type_)
  {
    dispatcher = new EpollDispatcher();
  }
  else
  {
    logTrace("loop type is not right:%d", type_);
    return false;
  }

  if(NULL == dispatcher)
  {
    logTrace("new EventDispatcher is failed");
    return false;
  }

  if(!dispatcher->initialize())
  {
    logTrace("dispatcher->initialize() is failed");
    return false;
  }

  return true;
}
bool EventLoop::addEvt(Socket *sock_,
    EvCallBack cb_,
    EventType evt_,
    void *arg_)
{
  if((NULL == sock_) || (-1 == sock_->getFd()) || (NULL == cb_))
  {
    logTrace("addEvt input is not valid,pleace check");
    return false;
  }

  if(!dispatcher->addEvt(this, sock_, cb_, evt_, arg_))
  {
    logTrace("addEvt event to loop is failed");
    return false;
  }

  sockMap[sock_->getFd()] = sock_;

  return true;
}
bool EventLoop::removeEvt(Socket *sock_,
    EventType evt_)
{
  if((NULL == sock_) || (-1 == sock_->getFd()))
  {
    logTrace("removeEvt input is not valid,pleace check");
    return false;
  }

  dispatcher->removeEvt(sock_, evt_);

  EventType evt = sock_->getEvt();
  if(0 == evt)
  {
    sockMap.erase(sock_->getFd());
  }

  return true;
}
int EventLoop::listen(int timeout_)
{
  while(1)
  {
    dispatcher->listen(sockMap, timeout_);
  }
}

主要调用前一篇中封装的三种事件监听方式,在初始化的时候选择一种event dipatcher,这就是面向接口编程的好处,利用多态,可以很方便的在运行时进行行为的改变。成员变量sockMap用于保存注册到EventLoop中的socket。

static void event_run_cb(struct event_context *ev, enum event_type type, void *data) { struct apsd_context *ctx = container_of(ev, struct apsd_context, ev); struct event_cb_context *cb; list_for_each_entry(cb, &ev->cb_list, list) { cb->cb(ctx, cb, type, data); } } static void event_hyfi_nl_cb(struct uloop_fd *fd, unsigned int events) { #define NETLINK_RCV_BUF BUF_SIZE*16 char buf[NETLINK_RCV_BUF]; struct event_context *ev = container_of(fd, struct event_context, hyfi_nl_fd); struct event_type_hyfi_bridge_context ev_ctx; struct nlmsghdr *nlh = (struct nlmsghdr *)buf; ssize_t len = 0; while ((len = recvfrom(fd->fd, (void *)nlh, NETLINK_RCV_BUF, MSG_DONTWAIT, NULL , NULL)) > 0) { if (NLMSG_OK(nlh, len)) { ev_ctx.type = nlh->nlmsg_type; ev_ctx.len = nlh->nlmsg_len - NLMSG_LENGTH(0); ev_ctx.data = NLMSG_DATA(nlh); event_run_cb(ev, EVENT_TYPE_HYFI_BRIDGE, &ev_ctx); } } } static void event_bridge_init(struct event_context *ev) { int sockfd; struct sockaddr_nl sockaddr; struct apsd_context *ctx = container_of(ev, struct apsd_context, ev); struct config_context *conf = &ctx->conf; sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_QCA_HYFI_EVENT); if (sockfd < 0) { SYS_DIE("socket"); } memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.nl_family = AF_NETLINK; sockaddr.nl_pid = getpid(); sockaddr.nl_groups = 0; if (bind(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) { SYS_DIE("bind"); } memset(&ev->hyfi_nl_fd, 0, sizeof(struct uloop_fd)); ev->hyfi_nl_fd.cb = event_hyfi_nl_cb; ev->hyfi_nl_fd.fd = sockfd; if (uloop_fd_add(&ev->hyfi_nl_fd, ULOOP_READ) < 0) { SYS_DIE("uloop_fd_add"); } event_bridge_set_event(conf); } 上面函数中ev->hyfi_nl_fd.cb = event_hyfi_nl_cb;event_hyfi_nl_cb为什么没有被传入参数?回调函数event_hyfi_nl_cb被执行时的struct uloop_fd *fd, unsigned int events参数是什么
最新发布
09-21
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值