libevent接口分析

环境配置与初始化

event_base_new

/**
 * Create and return a new event_base to use with the rest of Libevent.
 *
 * @return a new event_base on success, or NULL on failure.
 *
 * @see event_base_free(), event_base_new_with_config()
 */
EVENT2_EXPORT_SYMBOL
struct event_base *event_base_new(void){
	int i;
	struct event_base *base; //类似一个reactor
 
	if ((base = calloc(1, sizeof(struct event_base))) == NULL)
		event_err(1, "%s: calloc", __func__);
 
	detect_monotonic(); //检测系统是否支持monotonic时钟类型
	gettime(base, &base->event_tv);//将当前时间赋值给event_tv
 
	
	min_heap_ctor(&base->timeheap);//小根堆初始化
	TAILQ_INIT(&base->eventqueue);//初始化链表
	base->sig.ev_signal_pair[0] = -1;//初始化socket
	base->sig.ev_signal_pair[1] = -1;
	
	base->evbase = NULL;
	for (i = 0; eventops[i] && !base->evbase; i++) {//选择统一事件的方法
		base->evsel = eventops[i];
 
		base->evbase = base->evsel->init(base);//选择完之后调用epoll_init()
	}
 
	if (base->evbase == NULL)
		event_errx(1, "%s: no event mechanism available", __func__);
 
	if (evutil_getenv("EVENT_SHOW_METHOD")){
		event_msgx("libevent using: %s\n",
			   base->evsel->name);
	}
		
 
	/* allocate a single active event queue */
	event_base_priority_init(base, 1); 
	return (base);
}

evutil socket函数封装

evutil_make_socket_nonblocking

/** Do platform-specific operations as needed to make a socket nonblocking.

    @param sock The socket to make nonblocking
    @return 0 on success, -1 on failure
 */
EVENT2_EXPORT_SYMBOL
int evutil_make_socket_nonblocking(evutil_socket_t sock);

evutil_make_listen_socket_reuseable

/** Do platform-specific operations to make a listener socket reusable.

    Specifically, we want to make sure that another program will be able
    to bind this address right after we've closed the listener.

    This differs from Windows's interpretation of "reusable", which
    allows multiple listeners to bind the same address at the same time.

    @param sock The socket to make reusable
    @return 0 on success, -1 on failure
 */
EVENT2_EXPORT_SYMBOL
int evutil_make_listen_socket_reuseable(evutil_socket_t sock);//监听可复用

evutil_closesocket

/** Do the platform-specific call needed to close a socket returned from
    socket() or accept().

    @param sock The socket to be closed
    @return 0 on success (whether the operation is supported or not),
            -1 on failure
 */
EVENT2_EXPORT_SYMBOL
int evutil_closesocket(evutil_socket_t sock);
#define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s) //关闭socket

事件IO处理

event_new : 需要传递socket或者其他文件描述符(open,read,write)

/**
  Allocate and assign a new event structure, ready to be added.

  The function event_new() returns a new event that can be used in
  future calls to event_add() and event_del().  The fd and events
  arguments determine which conditions will trigger the event; the
  callback and callback_arg arguments tell Libevent what to do when the
  event becomes active.

  If events contains one of EV_READ, EV_WRITE, or EV_READ|EV_WRITE, then
  fd is a file descriptor or socket that should get monitored for
  readiness to read, readiness to write, or readiness for either operation
  (respectively).  If events contains EV_SIGNAL, then fd is a signal
  number to wait for.  If events contains none of those flags, then the
  event can be triggered only by a timeout or by manual activation with
  event_active(): In this case, fd must be -1.

  The EV_PERSIST flag can also be passed in the events argument: it makes
  event_add() persistent until event_del() is called.

  The EV_ET flag is compatible with EV_READ and EV_WRITE, and supported
  only by certain backends.  It tells Libevent to use edge-triggered
  events.

  The EV_TIMEOUT flag has no effect here.

  It is okay to have multiple events all listening on the same fds; but
  they must either all be edge-triggered, or all not be edge triggered.

  When the event becomes active, the event loop will run the provided
  callback function, with three arguments.  The first will be the provided
  fd value.  The second will be a bitfield of the events that triggered:
  EV_READ, EV_WRITE, or EV_SIGNAL.  Here the EV_TIMEOUT flag indicates
  that a timeout occurred, and EV_ET indicates that an edge-triggered
  event occurred.  The third event will be the callback_arg pointer that
  you provide.

  @param base the event base to which the event should be attached.
  @param fd the file descriptor or signal to be monitored, or -1.
  @param events desired events to monitor: bitfield of EV_READ, EV_WRITE,
      EV_SIGNAL, EV_PERSIST, EV_ET.
  @param callback callback function to be invoked when the event occurs
  @param callback_arg an argument to be passed to the callback function

  @return a newly allocated struct event that must later be freed with
    event_free() or NULL if an error occurred.
  @see event_free(), event_add(), event_del(), event_assign()
 */
EVENT2_EXPORT_SYMBOL
struct event *event_new(struct event_base *, evutil_socket_t, short, event_callback_fn, void *);
//event_callback_fn 是回调函数,自定义,在监听到消息时触发执行

缓冲IO

bufferevent

循环(loop)

event_base_dispatch

/**
   Event dispatching loop

  This loop will run the event base until either there are no more pending or
  active, or until something calls event_base_loopbreak() or
  event_base_loopexit().

  @param base the event_base structure returned by event_base_new() or
     event_base_new_with_config()
  @return 0 if successful, -1 if an error occurred, or 1 if we exited because
     no events were pending or active.
  @see event_base_loop()
 */
EVENT2_EXPORT_SYMBOL
int event_base_dispatch(struct event_base *);

简单实例:

// first_libevent.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <event2/event.h>
#include <event2/listener.h>
#include<string.h>
#ifndef _WIN32
#include<signal.h> //linux适配
#endif
#include <iostream>
using namespace std;
#define SPORT 5002

void listen_cb(struct evconnlistener *e, evutil_socket_t s, struct sockaddr * a, int socklen, void *arg)
{
	cout << "触发listen_cb函数" << endl;
}

int main()
{
#ifdef _WIN32
	//初始化socket库
	WSADATA wsa;
	WSAStartup(MAKEWORD(2,2), &wsa);
#else
	//忽略管道信号, 发送数据给已关闭的socket
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)return 1;
#endif
    std::cout << "test server!\n"; 
	event_base *base = event_base_new();
	if (base) 
	{
		cout << "event_base_new success" << endl;
	}
	//监听端口
	//socket, bind, listen, 绑定事件

	sockaddr_in sin;
	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(SPORT);

	evconnlistener *ev = evconnlistener_new_bind(base, //libevent的上下文
		listen_cb, //接收到连接的回调函数
		base, //回调函数获取参数arg
		LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, //地址重用,evconnlistener关闭同时关闭Socket
		10, //连接队列大小,对应listen函数
		(sockaddr*)&sin,	//绑定的地址和端口 
		sizeof(sin)
	);

	//事件分发处理
	if (base)event_base_dispatch(base);
	if (ev)evconnlistener_free(ev);

	if(base)
		event_base_free(base);
#ifdef _WIN32
	WSACleanup();
#endif

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值