libevent源代码分析-介绍、安装、使用

时间:2022-10-25 00:15:06

Libevent介绍

在include\event2\event.h中有关于Libevent的介绍,这里简单翻译介绍一下:
Libevent是以事件为驱动的开发可扩展的网络服务端的库。开放的API设置事件的回调函数,当事件来临时调用这个回调函数。它还支持信号和定时器。

开发者只需要简单的add/remove来将事件添加到event loop中,通过event_dispatch驱动event。

Libevent支持 /dev/poll, kqueue(2), select(2), poll(2),
epoll(4), and evports。内部的事件机制和应用接口相互独立,因此内部实现的更新不影响应用程序。Libevent可以用于多线程。

安装

在官网下载http://libevent.org。我下载了最新版本libevent-2.0.22-stable.tar.gz。放到目录,解压缩tar -zxvf ibevent-2.0.22-stable.tar.gz。
解压后进入目录,进行配置,把库安装到/usr目录下

./configure --prefix=/usr

编译安装

sudo make
sudo make install

查看是否安装成功:

ls -al /usr/lib|grep libevent
lrwxrwxrwx 1 root root 21 811 00:04 libevent-2.0.so.5 -> libevent-2.0.so.5.1.9
-rwxr-xr-x 1 root root 920932 811 00:04 libevent-2.0.so.5.1.9
-rw-r--r-- 1 root root 1309268 811 00:04 libevent.a
lrwxrwxrwx 1 root root 26 811 00:04 libevent_core-2.0.so.5 -> libevent_core-2.0.so.5.1.9
-rwxr-xr-x 1 root root 557242 811 00:04 libevent_core-2.0.so.5.1.9
-rw-r--r-- 1 root root 821804 811 00:04 libevent_core.a
-rwxr-xr-x 1 root root 974 811 00:04 libevent_core.la
lrwxrwxrwx 1 root root 26 811 00:04 libevent_core.so -> libevent_core-2.0.so.5.1.9
lrwxrwxrwx 1 root root 27 811 00:04 libevent_extra-2.0.so.5 -> libevent_extra-2.0.so.5.1.9
-rwxr-xr-x 1 root root 379504 811 00:04 libevent_extra-2.0.so.5.1.9
-rw-r--r-- 1 root root 487536 811 00:04 libevent_extra.a
-rwxr-xr-x 1 root root 981 811 00:04 libevent_extra.la
lrwxrwxrwx 1 root root 27 811 00:04 libevent_extra.so -> libevent_extra-2.0.so.5.1.9
-rwxr-xr-x 1 root root 939 811 00:04 libevent.la
lrwxrwxrwx 1 root root 29 811 00:04 libevent_openssl-2.0.so.5 -> libevent_openssl-2.0.so.5.1.9
-rwxr-xr-x 1 root root 90317 811 00:04 libevent_openssl-2.0.so.5.1.9
-rw-r--r-- 1 root root 110340 811 00:04 libevent_openssl.a
-rwxr-xr-x 1 root root 1010 811 00:04 libevent_openssl.la
lrwxrwxrwx 1 root root 29 811 00:04 libevent_openssl.so -> libevent_openssl-2.0.so.5.1.9
lrwxrwxrwx 1 root root 30 811 00:04 libevent_pthreads-2.0.so.5 -> libevent_pthreads-2.0.so.5.1.9
-rwxr-xr-x 1 root root 20571 811 00:04 libevent_pthreads-2.0.so.5.1.9
-rw-r--r-- 1 root root 14322 811 00:04 libevent_pthreads.a
-rwxr-xr-x 1 root root 1002 811 00:04 libevent_pthreads.la
lrwxrwxrwx 1 root root 30 811 00:04 libevent_pthreads.so -> libevent_pthreads-2.0.so.5.1.9
lrwxrwxrwx 1 root root 21 811 00:04 libevent.so -> libevent-2.0.so.5.1.9

例子

写各测试程序,编译时要设置参数-levent,连接libevent的库。

echoServer.cc

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <event.h>
#include <stdlib.h>
#include <unistd.h>

#define PORT 8000
#define BACKLOG 5
#define MEM_SIZE 1024

struct event_base* base;
struct sockEvent
{
struct event* readEvent;
struct event* writeEvent;
char* buffer;
};

void releaseSockEvent(struct sockEvent* ev)//delete from base and free it
{
event_del(ev->readEvent);
free(ev->readEvent);
free(ev->writeEvent);
free(ev->buffer);
free(ev);
}

void handleWrite(int sock, short event, void* arg)
{
char* buffer = (char*)arg;
send(sock, buffer, strlen(buffer), 0);

free(buffer);
}

void handldRead(int sock, short event, void* arg)
{
struct event* writeEvent;
int size;
struct sockEvent* ev = (struct sockEvent*)arg;
ev->buffer = (char*)malloc(MEM_SIZE);
bzero(ev->buffer, MEM_SIZE);
size = recv(sock, ev->buffer, MEM_SIZE, 0);
printf("receive data:%s, size:%d\n", ev->buffer, size);
if (size == 0) //client has send FIN
{
releaseSockEvent(ev);
close(sock);
return;
}
//add event to base to send the received data
event_set(ev->writeEvent, sock, EV_WRITE, handleWrite, ev->buffer);
event_base_set(base, ev->writeEvent);
event_add(ev->writeEvent, NULL);
}

void handleAccept(int sock, short event, void* arg)//when new connection coming, calling this func
{
struct sockaddr_in cli_addr;
int newfd;
socklen_t sinSize;
struct sockEvent* ev = (struct sockEvent*)malloc(sizeof(struct sockEvent));
ev->readEvent = (struct event*)malloc(sizeof(struct event));
ev->writeEvent = (struct event*)malloc(sizeof(struct event));
sinSize = sizeof(struct sockaddr_in);
newfd = accept(sock, (struct sockaddr*)&cli_addr, &sinSize);
//set the new coming connection event
event_set(ev->readEvent, newfd, EV_READ|EV_PERSIST, handldRead, ev);
event_base_set(base, ev->readEvent);
event_add(ev->readEvent, NULL);
}

int main(int argc, char* argv[])
{
struct sockaddr_in serverAddr;
int sock;

sock = socket(AF_INET, SOCK_STREAM, 0);
int on = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int));
//memset(&serverAddr, 0, sizeof(serverAddr));
bzero(&serverAddr, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = INADDR_ANY;
bind(sock, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr));
listen(sock, BACKLOG);

struct event listenEvent;
base = event_base_new();//Create new EventBase
event_set(&listenEvent, sock, EV_READ|EV_PERSIST, handleAccept, NULL);//conbine listenEvent and it's callback function
event_base_set(base, &listenEvent);
event_add(&listenEvent, NULL);
event_base_dispatch(base);//start base

return 0;
}