【Linux】Libevent库

news2024/11/16 16:27:59

Libevent——高性能I/O框架库

        底层封装了select,poll,epoll,便于使用

        I/O框架库以库函数的形式,封装了较为底层的系统调用,给应用程序提供了一组更便于使用的接口

特点:1.跨平台,2.统一事件源(I/O事件、信号、定时事件),3.libevent_pthreads库保证线程安全,4.基于Reactor模式(主线程只负责事件检测)

 Libevent框架:事件注册交给libevent,事件循环自动用select、poll、epoll检测事件,检测到后通知libevent调用注册的回调函数。


Libevent使用

使用分为三步:

1.注册事件交给libevent

 struct event_base *实例名= event_init();//struct event_base创建实例,初始化

 struct event *事件名= event_new(实例,信号,事件,回调函数,arg)//需要自己写回调函数

void 回调函数名(int fd, short event, void *arg)
{
   处理方式
}

 event_add(事件名, NULL);

2.启动事件循环,内部自动调用select或poll或epoll

 event_base_dispatch(实例名);

3.处理完成后释放

    event_free(事件名);
    event_base_free(实例名);

其中libevent支持的事件类型有:

#define EV_TIMEOUT 0x01 /* 定时事件 */
#define EV_READ 0x02 /* 可读事件 */
#define EV_WRITE 0x04 /* 可写事件 */
#define EV_SIGNAL 0x08 /* 信号事件 */
#define EV_PERSIST 0x10 /* 永久事件 */

//永久性事件取出检测完后还会放回待检测的链表中,可以一直检测 
/* 边沿触发事件,需要 I/O 复用系统调用支持,比如 epoll */
#define EV_ET 0x20

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <event.h>//libevent
#include <signal.h>//信号
//处理信号事件的回调函数
void signal_cb(int fd, short event, void *arg)
{
    if(event & EV_SIGNAL)//event短整型直接按位与比较
        printf("%d Signal triggered\n",fd);
}
//处理定时事件的回调函数
void timeout_cb(int fd, short event, void *arg)
{
    if(event & EV_TIMEOUT)
       printf("timeout\n");
}
int main()
{
    struct event_base *base = event_init();//struct event_base创建实例,初始化
    assert(base!=NULL);
//1.注册事件
    //定义一个信号事件
    //  event_new(属于的实例,信号,事件,处理事件的回调函数,传给回调函数的参数)
    struct event*signal_event = event_new(base,SIGINT,EV_SIGNAL|EV_PERSIST,signal_cb,NULL);
    assert(signal_event!=NULL);
    //添加事件
    event_add(signal_event, NULL);


    //创建定时事件
    //struct event *timeout_event = evtimer_new(base, timeout_cb, NULL);   
    struct event*timeout_event = event_new(base,-1,EV_TIMEOUT,timeout_cb,NULL);
    //等待时长
    struct timeval tv = { 5, 0 }; 
    //添加事件
    event_add(timeout_event, &tv);

//2.启动事件循环
    event_base_dispatch(base);

//3.返回处理后free掉注册信息和实例
    event_free(signal_event);
    event_free(timeout_event);
    event_base_free(base);

    exit(0);
}

当I/O,信号,定时事件的队列都为空,则event_base_dispatch结束,程序退出。

将信号注册为EV_PERSIST永久性事件 ,所以程序不会自动结束(一直有事件需要处理)

 若将定时事件注册为永久性事件,它每隔设定的秒都会调用回调函数


写一个TCP服务器端

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<event.h>
struct mess
{
    struct event * ev;
    //int cout;
};
int create_socket()
void recv_cb(int fd, short ev,void*arg)
{
    struct mess * s = (struct mess*)arg;
    if(ev & EV_READ)
    {
        char buff[128] = {0};
        int n = recv(fd,buff,127,0);
        if(n<=0)
        {
            event_free(s->ev);//关闭时要释放实例,需要获取地址,所以前面弄了一个结构体
            free(s);
            close(fd);
            printf("client close\n");
            return;
        }
        printf("buff=%s\n",buff);
        send(fd,"ok",2,0);
    }
}
void accept_cb(int fd, short ev,void*arg)
{
    struct event_base*base = (struct event_base*)arg;
    if(ev&EV_READ)//生成读事件了
    {
        struct sockaddr_in caddr;
        int len = sizeof(caddr);
        int c = accept(fd,(struct sockaddr*)&caddr,&len);
        if(c<0)return;
        printf("accept c=%d\n",c);
        //用recv_cb处理读事件
        struct event* c_ev = event_new(base,c,EV_READ|EV_PERSIST,recv_cb,base);
        if(c_ev==NULL)
        {
            close(c);
            return;
        }
        event_add(c_ev,NULL);
    }
}
int main()
{
    int sockfd = create_socket()
    assert(sockfd!=-1);
    
    struct event_base*base = event_init();
    assert(base!=NULL);

    //产生事件,用accept_cb处理
    struct event*sock_ev = event_new(base,sockfd,EV_READ|EV_PERSIST,accept_cb,NULL);
    assert(sock_ev!=NULL);
    event_add(sock_ev, NULL);//事件,超时时间
    
    event_base_dispatch(base);
    event_free(sock_ev);
    event_base_free(base);

    exit(0);
}
//创建套接字
int create_socket()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd==-1)
        return -1;
    struct sockaddr_in addr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    if(res==-1)return -1;

    res=listen(sockfd,5);
    if(res==-1)return -1;
    return sockfd;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/493399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++面向对象之封装、继承、和多态

一、封装 把客观事物封装成类&#xff0c;而且可以把自己的数据和方法设置为只能让可信的类或者对象操作&#xff0c;对不可信的信息进行隐藏&#xff08;利用public,private,protected,friend)实现 二、继承 2.1类与类的关系 has-a &#xff1a;描述一个类由多个部件类构成…

SpringCloud全面学习笔记之初尝美妙篇

目录 前言初识微服务单体架构分布式架构微服务架构初见SpringCloud微服务治理分布式服务架构案例 微服务组件及使用Eureka注册中心提供者和消费者Eureka的结构和作用搭建Eureka服务注册服务服务发现Eureka注册服务总结 Ribbon负载均衡原理负载均衡原理负载均衡策略懒加载 Nacos…

Qt quick基础2(包含平移旋转放缩以及qml控件大写开头啊)

Qt quick基础2&#xff08;包含平移旋转放缩以及qml控件大写开头啊&#xff09; 目录 Qt quick基础2&#xff08;包含平移旋转放缩以及qml控件大写开头啊&#xff09;前言简单的平移、旋转和放缩其他元素的一些基本使用qml文件作为控件时&#xff0c;务必以大写字母开头命名小结…

力扣题库刷题笔记682-棒球比赛

1、题目如下&#xff1a; 2、个人Python代码实现如下&#xff1a; 代码如下&#xff1a; class Solution: def calPoints(self, operations: List[str]) -> int: i 0 #用于遍历元素的下标 while i < len(operations): …

【Python入门篇】——Python基础语法(数据类型与数据类型转换)

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; Python入门&#xff0c;本专栏主要内容为Python的基础语法&#xff0c;Python中的选择循环语句…

数据结构与算法导学

文章目录 数据结构和算法导学认识数据结构认识算法总结 数据结构和算法导学 程序 数据结构 算法 认识数据结构 什么是数据结构&#xff1f; 数据结构是一门研究计算机中数据存储和数据操作的学科。 为什么要学习数据结构&#xff1f; 学习数据结构能让我们写出更加优秀的代码…

关于在线帮助中心你需要思考以下几个问题

搭建帮助中心是大多数企业都在尝试做的事情&#xff0c;它的重要性对于企业来说不言而喻。现在对于企业来说&#xff0c;搭建帮助中心或许不是什么难事&#xff0c;但是关于帮助中心&#xff0c;有几个问题需要思考清楚&#xff0c;才能让其发挥最大的价值。 一、如何让用户养成…

CAS 原子操作类

CAS 原子类 java.util.concurrent.atomic 是什么 CAS compare and swap的缩写&#xff0c;中文翻译比较并交换&#xff0c;实现并发算法时常用的一种技术 它包含三个操作数–内存位置、预期原值及更新值 执行CAS操作时&#xff0c;将内存位置的值与预期原值比较 如果相匹…

网络协议与攻击模拟-05-ICMP协议

ICMP 协议 1、理解 ICMP 协议 2、理解 ICMP 重定向 3、会使用 wireshark 分析 ICMP 重定向流量实验 一、 ICMP 基本概念 1、 ICMP 协议 Internet 控制报文协议&#xff0c;用于在 IP 主机、路由器之间传递控制消息&#xff0c;控制消息指网络通不通、主机是否可达、路由是否…

荔枝派Zero(全志V3S)驱动开发之hello驱动程序

文章目录 前言一、设备驱动分类二、字符设备驱动简介三、字符设备驱动开发1、APP打开的文件在内核中如何表示2、编写驱动程序的步骤3、hello 驱动程序编写<1>、试验程序编写<2>、测试程序编写<3>、编写 Makefile<4>、编译 3、运行测试<1>、上传程…

PyTorch实战4:猴痘病识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;365天深度学习训练营-第P4周&#xff1a;猴痘病识别&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 目录 一、搭建CNN网络结构1、原文网络结构1.1、网络…

4。计算机组成原理(2)存储系统

嵌入式软件开发&#xff0c;非科班专业必须掌握的基本计算机知识 核心知识点&#xff1a;数据表示和运算、存储系统、指令系统、总线系统、中央处理器、输入输出系统 这一部分主要讲解了CPU的组成和扩容、CPU与存储器&#xff08;主存、辅存、缓存&#xff09;的连接 一 存储…

C++笔记——第十六篇 异常

目录 1.C语言传统的处理错误的方式 2. C异常概念 3. 异常的使用 3.1 异常的抛出和捕获 在函数调用链中异常栈展开匹配原则 3.2异常安全 4.异常的优缺点 1.C语言传统的处理错误的方式 传统的错误处理机制&#xff1a; 1. 终止程序&#xff0c;如assert&#xff0c;缺陷&a…

飞腾ft2000-麒麟V10-SP1安装Docker、运行gitlab容器

目录 一、安装及配置docker 1、卸载docker相关包及删除相关配置文件 2、安装二进制docker 1.下载软件包 2.解压 3.修改镜像加速地址 4.修改profile文件 5.启动docker 6.docker常用命令 二、安装并启动gitlab镜像 1.安装gitlab镜像 1.查询满足使用需求的gitlab版本 2…

很佩服的一个Google大佬,离职了。。

这两天&#xff0c;科技圈又有一个突发的爆款新闻相信不少同学都已经看到了。 那就是75岁的计算机科学家Geoffrey Hinton从谷歌离职了&#xff0c;从而引起了科技界的广泛关注和讨论。 而Hinton自己也证实了这一消息。 提到Geoffrey Hinton这个名字&#xff0c;对于一些了解过…

使用 Mercury 直接从 Jupyter 构建 Web 程序

动动发财的小手&#xff0c;点个赞吧&#xff01; 有效的沟通在所有数据驱动的项目中都至关重要。数据专业人员通常需要将他们的发现和见解传达给利益相关者&#xff0c;包括业务领导、技术团队和其他数据科学家。 虽然传达数据见解的传统方法&#xff08;如 PowerPoint 演示文…

Oracle SQL优化相关数据项

要掌握SQL调优技术,就需要能读懂SQL语句的执行计划,要想读懂SQL语句的执行计划,不仅需要准确理解SQL语句执行计划中各操作及其含义,还需要准确理解SQL语句执行计划中各数据项的含义。本书第7章中,已经对SQL语句执行计划中各个操作的含义做了详尽的阐述,本章中,我们将对S…

爱普特APT32F110x系列时钟介绍

最近要用APT32F110x做一些开发&#xff0c;顺便学习一下。 APT32F110x 是由爱普特推出的基于平头哥&#xff08;T-Head Microsystems&#xff09;CPU 内核开发的 32 位高性能低成本单片机。 APT32F1104x基于嵌入式 Flash 工艺制造&#xff0c;内部丰富的模拟资源&#xff0c;包…

ShardingJDBC核心概念与快速实战

目录 ShardingSphere介绍 ShardingSphere特点 ShardingSphere简述 ShardingSphere产品区分 ShardingJDBC实战 核心概念 实战 ShardingJDBC的分片算法 ShardingSphere目前提供了一共五种分片策略&#xff1a; 分库分表带来的问题 ShardingSphere介绍 ShardingSphere特…

结合SSE实现实时位置展示与轨迹展示

概述 实时位置与实时轨迹的展示是webgis中非常常见的一个功能&#xff0c;本文结合SSE来实现实现此功能。 SSE简介 SSE是Sever-Sent Event的首字母缩写&#xff0c;它是基于HTTP协议的&#xff0c;在服务器和客户端之间打开一个单向通道&#xff0c;服务端响应的不再是一次性…