服务器并发编程--libevent

2024-05-06 09:12

本文主要是介绍服务器并发编程--libevent,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、Libevent概述
    • 1.两个重要的结构体
    • 2.libevent常用接口
  • 二、libevent IO事件
  • 三、libevent信号事件
  • 四、libevent高并发服务器
  • 参考

一、Libevent概述

Libevent 是一个用C语言编写的、轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大;源代码相当精炼、易读;跨平台,支持 Windows、 Linux、 *BSD 和 Mac Os;支持多种 I/O 多路复用技术, epoll、 poll、 dev/poll、 select 和 kqueue 等;支持 I/O,定时器和信号等事件;注册事件优先级。
 
  Libevent 已经被广泛的应用,作为底层的网络库;比如 memcached、 Vomit、 Nylon、 Netchat等等。Libevent之于C语言网络编程,类似于Nettty之于Java Web编程。学习Netty的小伙伴,不防看下Libevent的实现,会加深对Netty框架的理解

安装方式(1):

$ apt-get download libevent-dev
$ dpkg -x  libevent-dev_2.1.12-stable-1build3_amd64.deb libevent

安装方式():

  • libevent的download urls
  • github assert

1.两个重要的结构体

struct event-base

  • 事件集合
  • struct event_base用于创建和管理事件循环,而struct event用于表示具体的事件,并与事件循环相关联。
  • struct event_base 代表一个事件处理的基础框架,它负责管理事件循环(event loop),接收事件并将它们分派给相应的事件处理器。
  • struct event_base 实例典型地代表了一个事件驱动程序的运行环境,它可以被视为事件循环的主体。
  • struct event_base 可以支持多种事件驱动的后端(如select、poll、epoll等),因此在创建 struct event_base 实例时,可以指定使用的后端。

struct event

  • 一个事件(可以是一个fd,也可以是一个signal,也可以是一个定时器事件)
  • struct event 包含了事件的相关信息,比如事件类型(读、写、定时器等)、事件触发时需要执行的回调函数等。
  • 当文件描述符上发生关注的事件时,struct event 将通知 struct event_base,然后 struct event_base 将事件分派给相应的事件处理器执行。

两者关系:

  • struct event结构体中有一个指向struct event_base的指针,用于指示该事件所属的事件循环。这样,当事件发生时,事件循环可以根据事件的描述找到相应的回调函数并执行。

2.libevent常用接口

event_init

  • 用于初始化 libevent 的全局状态。在使用 libevent 前调用此函数是必要的步骤,它会进行一些全局状态的初始化工作。

event_base new

  • event_base_new 用于创建一个新的事件基础框架(struct event_base 实例)。
  • 返回的 event_base 实例将用于管理事件循环和事件处理。

event_set

  • event_set 用于设置事件的相关属性,比如事件关联的文件描述符、事件类型、以及事件触发时执行的回调函数。
    这个函数被废弃了,不建议使用,建议使用 event_assign 替代。

event_assign

  • event_assign 用于将事件与指定的 event_base 关联起来,并设置事件的属性。
  • 这个函数类似于 event_set,但是更加灵活,可以避免一些使用上的混淆。

event_add

  • event_add 用于向事件循环中添加一个事件,让它开始监视文件描述符上的事件。
  • 添加事件后,事件循环将开始监视文件描述符,当有事件发生时,会触发事件的回调函数。

evconnlistener_new_bing

  • evconnlistener_new_bind 是用于创建一个监听器(listener)的函数,用于监听指定地址和端口上的连接请求。
  • 当有连接请求到达时,监听器将接受连接并创建一个新的套接字来处理该连接。

二、libevent IO事件

fifo-read.c


#include <event.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>void fifo_read(evutil_socket_t fd, short events, void *arg) {char buf[32] = {0};int rt = read(fd, buf, sizeof(buf));if (-1 == rt) {perror("read");exit(-1);}printf("read <%s>\n", buf);return;
}int main() {int ret = mkfifo("fifo.tmp", 0700);if (-1 == ret) {perror("mkfifo");exit(-1);}int fd = open("fifo", O_RDONLY);if (-1 == fd) {perror("open");exit(-1);}struct event ev;event_init();event_set(&ev, fd, EV_READ, fifo_read, NULL);event_add(&ev, NULL);event_dispatch();return 0;
}

fifo-write.c

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main() {int fd = open("fifo.tmp", O_WRONLY);if (-1 == fd) {perror("open");exit(-1);}char buf[32] = {0};while (1) {scanf("%s", buf);int ret = write(fd, buf, sizeof(buf));if (-1 == ret) {perror("write");exit(-1);}if (!strcmp(buf, "bye")) {break;}memset(buf, 0, sizeof(buf));}return 0;
}

三、libevent信号事件

signal.c

#include <event2/event_compat.h>
#include <event2/event_struct.h>
#include <signal.h>static int signal_count = 0;void signal_handler(evutil_socket_t fd, short events, void *args) {printf("<sig: %d>\n", fd);++signal_count;if (signal_count >= 2) {event_del((struct event *)args);}
}int main() {struct event_base *base = event_base_new();struct event ev;event_assign(&ev, base, SIGINT, EV_SIGNAL | EV_PERSIST, signal_handler, &ev);event_add(ev, NULL);event_base_dispatch();event_base_free(base);return 0;
}

四、libevent高并发服务器

#include <arpa/inet.h>
#include <cstddef>
#include <event2/bufferevent.h>
#include <event2/bufferevent_struct.h>
#include <event2/event_compat.h>
#include <event2/listener.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void read_cb(struct bufferevent *bev, void *ctx) {char buf[128] = {0};size_t ret = bufferevent_read(bev, buf, sizeof(buf));if (ret < 0) {exit(-1);}printf("read from: <%d>\n", *(int *)ctx);
}void event_cb(struct bufferevent *bev, short what, void *ctx) {if (what & BEV_EVENT_EOF)printf("Client: <d> down", *(int *)ctx);bufferevent_free(bev);
}void listen_cb(struct evconnlistener *listener, evutil_socket_t fd,struct sockaddr *addr, int socklen, void *arg){static int gFd = -1;printf("Accept: <%d>\n", fd);gFd = fd;struct event_base *base = arg;struct bufferevent *bev =bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);if (NULL == bev) {exit(-1);}bufferevent_setcb(bev, read_cb, NULL, event_cb, &gFd);bufferevent_enable(bev, EV_READ);
}int main() {struct event_base *base = event_base_new();if (NULL == base) {printf("event_base \n");exit(-1);}struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = 8000;server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");struct evconnlistener *listen = evconnlistener_new_bind(base, listen_cb, NULL, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 10,(const struct sockaddr *)&server_addr, sizeof(server_addr));event_base_dispatch(base);evconnlistener_free(listen);event_base_free(base);return 0;
}

参考

  • 服务器并发编程–libevent
  • Libevent初探

这篇关于服务器并发编程--libevent的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/963970

相关文章

Linux高并发场景下的网络参数调优实战指南

《Linux高并发场景下的网络参数调优实战指南》在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃,本文基于真实案例分析,从参数解读、问题诊断到优... 目录一、问题背景:当并发连接遇上性能瓶颈1.1 案例环境1.2 初始参数分析二、深度诊断:连接状态与

Python 异步编程 asyncio简介及基本用法

《Python异步编程asyncio简介及基本用法》asyncio是Python的一个库,用于编写并发代码,使用协程、任务和Futures来处理I/O密集型和高延迟操作,本文给大家介绍Python... 目录1、asyncio是什么IO密集型任务特征2、怎么用1、基本用法2、关键字 async1、async

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

springboot上传zip包并解压至服务器nginx目录方式

《springboot上传zip包并解压至服务器nginx目录方式》:本文主要介绍springboot上传zip包并解压至服务器nginx目录方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录springboot上传zip包并解压至服务器nginx目录1.首先需要引入zip相关jar包2.然

将Java项目提交到云服务器的流程步骤

《将Java项目提交到云服务器的流程步骤》所谓将项目提交到云服务器即将你的项目打成一个jar包然后提交到云服务器即可,因此我们需要准备服务器环境为:Linux+JDK+MariDB(MySQL)+Gi... 目录1. 安装 jdk1.1 查看 jdk 版本1.2 下载 jdk2. 安装 mariadb(my

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

基于Python打造一个可视化FTP服务器

《基于Python打造一个可视化FTP服务器》在日常办公和团队协作中,文件共享是一个不可或缺的需求,所以本文将使用Python+Tkinter+pyftpdlib开发一款可视化FTP服务器,有需要的小... 目录1. 概述2. 功能介绍3. 如何使用4. 代码解析5. 运行效果6.相关源码7. 总结与展望1

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.