我是靠谱客的博主 害怕导师,最近开发中收集的这篇文章主要介绍libeventlibevent是什么下载编译示例,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • libevent是什么
    • 特点
    • 组件
    • 功能
    • Reactor(反应器)模式
  • 下载
  • 编译
    • Visual Studio 2019 on Windows
    • 64位静态库
  • 示例
    • 示例一
    • 示例二

libevent是什么

  • libevent是一个轻量级的开源的高性能的事件触发的网络库,适用于windows、linux、bsd等多种平台,内部使用select、epoll、kqueue等系统调用管理事件机制。它被众多的开源项目使用,例如大名鼎鼎的memcached等。
  • 基本的socket编程是阻塞/同步的,每个操作除非已经完成或者出错才会返回,这样对于每一个请求,要使用一个线程或者单独的进程去处理,系统资源没法支撑大量的请求(c10k problem),例如内存:默认情况下每个线程需要占用2~8M的栈空间。posix定义了可以使用异步的select系统调用,但是因为其采用了轮询的方式来判断某个fd是否变成active,效率不高[O(n)],连接数一多,也还是撑不住。于是各系统分别提出了基于异步/callback的系统调用,例如Linux的epoll,BSD的kqueue,Windows的IOCP。由于在内核层面做了支持,所以可以用O(1)的效率查找到active的fd。基本上,libevent就是对这些高效IO的封装,提供统一的API,简化开发。

特点

  • 事件驱动,高性能;
  • 轻量级,专注于网络(相对于ACE);
  • 开放源码,代码相当精炼、易读;
  • 跨平台,支持Windows、Linux、BSD和Mac OS;
  • 支持多种I/O多路复用技术(epoll、poll、dev/poll、select和kqueue等),在不同的操作系统下,做了多路复用模型的抽象,可以选择使用不同的模型,通过事件函数提供服务;
  • 支持I/O,定时器和信号等事件;
  • 采用Reactor模式;

组件

  • libevent_core
    所有核心的事件和缓冲功能,包含了所有的event_base、evbuffer、bufferevent和工具函数。
  • libevent_extra
    定义了程序可能需要,也可能不需要的协议特定功能,包括HTTP、DNS和RPC。
  • libevent
    这个库因为历史原因而存在,它包含libevent_core和libevent_extra的内容。不应该使用这个库,未来版本的libevent可能去掉这个库。
  • libevent_pthreads
    添加基于pthread可移植线程库的线程和锁定实现。它独立于libevent_core,这样程序使用libevent时就不需要链接到pthread,除非是以多线程方式使用libevent。

功能

Libevent提供了事件通知,IO缓存事件,定时器,超时,异步解析DNS,事件驱动的HTTP Server以及一个RPC框架。

  • 事件通知:当文件描述符可读可写时将执行回调函数。
  • IO缓存:缓存事件提供了输入输出缓存,能自动的读入和写入,用户不必直接操作IO。
  • 定时器:libevent提供了定时器的机制,能够在一定的时间间隔之后调用回调函数。
  • 信号:触发信号,执行回调。
  • 异步的dns解析:libevent提供了异步解析dns服务器的dns解析函数集。
  • 事件驱动的HTTP服务器:libevent提供了一个简单的,可集成到应用程序中的HTTP服务器。
  • RPC客户端服务器框架:libevent为创建RPC服务器和客户端创建了一个RPC框架,能自动的封装和解封数据结构。

Reactor(反应器)模式

libevent是一个典型的reactor模式的实现。Reactor 模型的几个组件:事件源(文件描述符,Socket或Handle)、Reactor 框架、多路复用机制和事件处理程序。

  • 普通的函数调用机制:程序调用某个函数,函数执行,程序等待,函数将结果返回给调用程序(如果含有函数返回值的话),也就是顺序执行的。
  • Reactor模式的基本流程:应用程序需要提供相应的接口并且注册到reactor反应器上,如果相应的事件发生的话,那么reactor将自动调用相应的注册的接口函数(类似于回调函数)通知你,所以libevent是事件触发的网络库。

下载

lievent

编译

Visual Studio 2019 on Windows

  • 修改libevent-2.1.11WIN32-Codenmakeevent2event-config.h
/* Define to 1 if you have the <stdint.h> header file. */
/ * #define EVENT__HAVE_STDINT_H 1 */
改为
/* Define to 1 if you have the <stdint.h> header file. */
#define EVENT__HAVE_STDINT_H 1 
  • 环境
**************************************************************
** Visual Studio 2019 Developer Command Prompt v16.5.2
** Copyright (c) 2019 Microsoft Corporation
*************************************************************

C:Program Files (x86)Microsoft Visual Studio2019Enterprise>
  • 命令
nmake /f Makefile.nmake
CORE_OBJS=event.obj buffer.obj bufferevent.obj bufferevent_sock.obj 
	bufferevent_pair.obj listener.obj evmap.obj log.obj evutil.obj 
	strlcpy.obj signal.obj bufferevent_filter.obj evthread.obj 
	bufferevent_ratelim.obj evutil_rand.obj evutil_time.obj
WIN_OBJS=win32select.obj evthread_win32.obj buffer_iocp.obj 
	event_iocp.obj bufferevent_async.obj
EXTRA_OBJS=event_tagging.obj http.obj evdns.obj evrpc.obj

!IFDEF OPENSSL_DIR
SSL_OBJS=bufferevent_openssl.obj
SSL_LIBS=libevent_openssl.lib
!ELSE
SSL_OBJS=
SSL_LIBS=
!ENDIF

ALL_OBJS=$(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS) $(SSL_OBJS)
STATIC_LIBS=libevent_core.lib libevent_extras.lib libevent.lib $(SSL_LIBS)

libevent_core.lib: $(CORE_OBJS) $(WIN_OBJS)
	lib $(LIBFLAGS) $(CORE_OBJS) $(WIN_OBJS) /out:libevent_core.lib 

libevent_extras.lib: $(EXTRA_OBJS)
	lib $(LIBFLAGS) $(EXTRA_OBJS) /out:libevent_extras.lib

libevent.lib: $(CORE_OBJS) $(WIN_OBJS) $(EXTRA_OBJS)
	lib $(LIBFLAGS) $(CORE_OBJS) $(EXTRA_OBJS) $(WIN_OBJS) /out:libevent.lib

libevent_openssl.lib: $(SSL_OBJS)
	lib $(LIBFLAGS) $(SSL_OBJS) /out:libevent_openssl.lib
  • 静态库
    • libevent.lib
    • libevent_core.lib
    • libevent_extras.lib

64位静态库

在这里插入图片描述

示例

示例一

#include <iostream>
#include <WinSock2.h>
#include "event.h"

#pragma comment(lib,"ws2_32.lib")
//#pragma comment(lib,"libevent.lib")
#pragma comment(lib,"libevent_core.lib")
//#pragma comment(lib,"libevent_extras.lib")

void OnTime(int sock, short event_value, void* arg)
{
    std::cout << "Hello World!n";

    timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;

    event_add((struct event*)arg, &tv);
}

int main()
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        return -1;
    }

    event_init();

    struct event ev_time;

    evtimer_set(&ev_time, OnTime, &ev_time);

    struct timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;

    event_add(&ev_time, &tv);

    event_dispatch();

    WSACleanup();

    return 0;
}

示例二

#include <iostream>
#include <WinSock2.h>
#include "event.h"

using namespace std;

#pragma comment(lib, "ws2_32.lib")
//#pragma comment(lib, "libevent.lib")
#pragma comment(lib, "libevent_core.lib")
//#pragma comment(lib, "libevent_extras.lib")

// 回调函数声明
void do_accept(evutil_socket_t listener, short event, void* arg);
void read_cb(struct bufferevent* bev, void* arg);
void error_cb(struct bufferevent* bev, short event, void* arg);
void write_cb(struct bufferevent* bev, void* arg);

int main()
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        return -1;
    }
    
    // 创建SOCKET    
    int ret = 0;
    evutil_socket_t listener;
    listener = socket(AF_INET, SOCK_STREAM, 0);

    evutil_make_listen_socket_reuseable(listener);    

    // 绑定本地地址
    SOCKADDR_IN sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = ADDR_ANY;
    sin.sin_port = htons(6789);
    if (bind(listener, (SOCKADDR*)&sin, sizeof(sin)) < 0)
    {
        cout << "bind出错!" << endl;
        return -1;
    }
    if (listen(listener, 32) < 0)
    {
        cout << "listen出错!" << endl;
        return -1;
    }
    cout << "正在监听……" << endl;

    // <A>设置SOCKET无阻塞模式
    evutil_make_socket_nonblocking(listener);

    // (1)创建“事件管理器”
    struct event_base* base = event_base_new();
    if (NULL == base)
    {
        cout << "event_base_new出错!" << endl;
        return -1;
    }

    // (2)创建事件
    struct event* listen_event = event_new(base, listener, EV_READ | EV_PERSIST, do_accept, (void*)base);

    // (3)添加事件
    event_add(listen_event, NULL);

    // (4)启动事件管理循环
    event_base_dispatch(base);

    cout << "Done!" << endl;
    return 0;
}

void do_accept(evutil_socket_t listener, short event, void* arg)
{
    struct event_base* base = (struct event_base*)arg;
    SOCKADDR_IN sin;
    int slen = sizeof sin;
    evutil_socket_t fd = accept(listener, (SOCKADDR*)&sin, &slen);
    if (fd < 0)
    {
        cout << "accept出错!" << endl;
        return;
    }
    
    //if (fd > FD_SETSIZE)
    //{
    //    cout << "accept返回fd超出FD_SETSIZE限制" << endl;
    //    return;
    //}
    
    cout << "accept:fd=" << fd << endl;

    // <B>创建“读写事件管理器”,自libevent2之后才有的
    struct bufferevent* bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);

    // <C>设置“读写事件管理器”的回调函数
    bufferevent_setcb(bev, read_cb, NULL, error_cb, arg);

    // <D>启动“读写事件管理器”
    bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);
}

void read_cb(struct bufferevent* bev, void* arg)
{
    #define MAX_LINE    256
    char szLine[MAX_LINE + 1];
    evutil_socket_t fd = bufferevent_getfd(bev);

    int n = 0;
    while (n = bufferevent_read(bev, szLine, MAX_LINE), n > 0)
    {
        szLine[n] = '';
        cout << "Read Line:" << szLine << endl;
        bufferevent_write(bev, szLine, n);
    }
}

void write_cb(struct bufferevent* bev, void* arg)
{

}

void error_cb(struct bufferevent* bev, short event, void* arg)
{
    evutil_socket_t fd = bufferevent_getfd(bev);
    cout << "error:fd=" << fd << endl;
    if (event & BEV_EVENT_TIMEOUT)
    {
        cout << "Time out!" << endl;
    }
    else if (event & BEV_EVENT_EOF)
    {
        cout << "EOF!" << endl;
    }
    else if (event & BEV_EVENT_ERROR)
    {
        cout << "Error!" << endl;
    }
    bufferevent_free(bev);
}

最后

以上就是害怕导师为你收集整理的libeventlibevent是什么下载编译示例的全部内容,希望文章能够帮你解决libeventlibevent是什么下载编译示例所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部