记录 Libevent的常用功能示例

2023-11-05

介绍

Libevent是开源社区一款高性能的I/O框架库,是reactor模式的优秀体现。网上相关资料很多,这篇博文主要以尽量简练的代码实现TcpServer服务器功能,代码覆盖大部分的常用函数接口。通过代码能对Libevent的整体框架,函数使用有直观的理解,配置好Libevent库的前提下,下方代码可直接复制运行。

代码

#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <thread>
#include <unordered_map>
#include <utility>
#include <signal.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>

//读取客户端
void do_read(evutil_socket_t fd, short event, void *arg) 
{
	printf("do_read! fd=%d threadid=%d ", fd, std::this_thread::get_id());

	//继续等待接收数据  
	char buf[1024] = {0};    
	int len = recv(fd, buf, 1024, 0);
	if (len > 0) 
	{
		printf("data=%s\n", buf);
		send(fd, buf, len, 0); 
	}
	else if (len == 0)
	{
		printf("client close\n");
		struct event *ev = (struct event *)arg;
		event_free(ev);
		closesocket(fd);
	}
}

void read_cb(struct bufferevent *bev, void *arg)
{
	evutil_socket_t fd = bufferevent_getfd(bev);
	evbuffer *evBuf = bufferevent_get_input(bev);
	int size = evbuffer_get_length(evBuf);

	char data[128] = {0};
	int len = evbuffer_remove(evBuf, data, size);
	printf("read_cb fd=%d threadid=%d size=%d data=%s\n", fd, std::this_thread::get_id(), size, data);

	send(fd, data, len, 0);
}

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);
	printf("fd = %d, ", fd);

	if (event & BEV_EVENT_TIMEOUT)
		printf("Timed out\n");
	else if (event & BEV_EVENT_EOF)
		printf("Connection closed\n");
	else if (event & BEV_EVENT_ERROR)
		printf("Other error\n");

	bufferevent_free(bev);
}

//回调函数,用于监听连接进来的客户端socket
void do_accept(evutil_socket_t fd, short event, void *arg) 
{   
	struct sockaddr_in client_addr; //客户端网络地址结构体   
	int in_size = sizeof(struct sockaddr_in);

	//客户端socket  
	int client_socketfd = accept(fd, (struct sockaddr *) &client_addr, &in_size); //等待接受请求,这边是阻塞式的  
	if (client_socketfd < 0) 
	{
		puts("accpet error");
		exit(1);
	}

	printf("do_accept! fd=%d threadid=%d\n", client_socketfd, std::this_thread::get_id());

	//类型转换
	struct event_base *base_ev = (struct event_base *)arg;

	//socket发送欢迎信息  
	char msg[] = "Welcome to Connect!";
	int size = send(client_socketfd, msg, strlen(msg), 0);

	//创建一个事件,这个事件主要用于监听和读取客户端传递过来的数据 持久类型
#if 0
	struct event *ev = event_new(base_ev, client_socketfd, EV_TIMEOUT | EV_READ | EV_PERSIST, do_read, event_self_cbarg());
	event_add(ev, NULL);
#else
	struct bufferevent *bev = bufferevent_socket_new(base_ev, client_socketfd, BEV_OPT_CLOSE_ON_FREE);
	bufferevent_setcb(bev, read_cb, NULL, error_cb, base_ev);
	bufferevent_enable(bev, EV_READ | EV_WRITE | EV_PERSIST);
	bufferevent_setwatermark(bev, EV_READ, 0, 0);
#endif

}

void signal_cb(evutil_socket_t fd, short event, void *arg)
{
	struct event *signal = (struct event *)arg;

	printf("signal_cb: got signal %d\n", event_get_signal(signal));
	event_del(signal);

	event_base_loopbreak(event_get_base(signal));
}

int main(int argc, char **argv)
{
	//初始化windows socket库
	WORD wVersionRequested = MAKEWORD(2, 2);
	WSADATA wsa_data;
	WSAStartup(0x0201, &wsa_data);
 
	struct sockaddr_in server_addr;   //服务器网络地址结构体    
	memset(&server_addr, 0, sizeof(server_addr)); //数据初始化--清零    
	server_addr.sin_family = AF_INET; //设置为IP通信    
	server_addr.sin_addr.s_addr = INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上    
	server_addr.sin_port = htons(8888); //服务器端口号    

	//创建服务端套接字  
	int server_socketfd = socket(PF_INET, SOCK_STREAM, 0);
	if (server_socketfd < 0) 
	{
		puts("socket error");
		return 0;
	}

	evutil_make_listen_socket_reuseable(server_socketfd); //设置端口重用
	evutil_make_socket_nonblocking(server_socketfd); //设置无阻塞

	//绑定IP  
	if (bind(server_socketfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0) 
	{
		puts("bind error");
		return 0;
	}

	//监听 监听队列长度  
	listen(server_socketfd, 10);

	printf("Server Start! main threadid=%d\n", std::this_thread::get_id());

	auto func = [=]() 
	{
		//创建event_base 事件的集合,多线程的话 每个线程都要初始化一个event_base
		struct event_base *base_ev = event_base_new();

		//创建一个事件,类型为持久性EV_PERSIST,回调函数为do_accept(主要用于监听连接进来的客户端)
		//将base_ev传递到do_accept中的arg参数
		struct event *ev = event_new(base_ev, server_socketfd, EV_TIMEOUT | EV_READ | EV_PERSIST, do_accept, base_ev);
		event_add(ev, NULL);

		//信号事件
		struct event *signal_int = evsignal_new(base_ev, SIGINT, signal_cb, event_self_cbarg());
		event_add(signal_int, NULL);

		//事件循环
		event_base_dispatch(base_ev);
		//销毁event_base
		event_base_free(base_ev);
	};

	std::thread thread(func);
	thread.join();

	printf("Server Stop\n");
	WSACleanup();

	getchar();
	return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

记录 Libevent的常用功能示例 的相关文章

  • 向进度条添加百分比文本 C#

    我有一个方法可以显示进程栏何时正在执行以及何时成功完成 我工作得很好 但我想添加一个百分比 如果完成 则显示 100 如果卡在某个地方 则显示更少 我在网上做了一些研究 但我无法适应我正在寻找的解决方案 这是我的代码 private voi
  • 每个托管线程是否都有自己对应的本机线程?

    我想知道是否在 Net 中创建托管线程 通过调用Thread Start 导致在后台创建一个本机线程 那么托管线程是否有对应的本机线程呢 如果是 当托管线程等待或睡眠时 是否意味着相应的本机线程也在等待或睡眠 是的 NET 线程映射到所有当
  • 未提供参数时如何指定 C# System.Commandline 行为?

    在我的控制台应用程序中 当未提供控制台参数时 将执行我指定列表 在本例中为参数 3 的任何处理程序 调用该处理程序时 布尔参数设置为 false 但对我来说 根本不调用它更有意义 如何防止这种情况发生并显示帮助文本 using System
  • MVC 在布局代码之前执行视图代码并破坏我的脚本顺序

    我正在尝试将所有 javascript 包含内容移至页面底部 我正在将 MVC 与 Razor 一起使用 我编写了一个辅助方法来注册脚本 它按注册顺序保留脚本 并排除重复的内容 Html RegisterScript scripts som
  • 当我们想要返回对象的引用时,为什么我们在赋值运算符中返回 *this 而通常(而不是 this)?

    我正在学习 C 和指针 我以为我理解了指针 直到我看到这个 一方面 asterix 运算符是解引用的 这意味着它返回值所指向的地址中的值 而与号 运算符则相反 它返回值存储的地址记忆 现在阅读有关赋值重载的内 容 它说 我们返回 this因
  • 如何创建包含 IPv4 地址的文本框? [复制]

    这个问题在这里已经有答案了 如何制作一个这样的文本框 我想所有的用户都见过这个并且知道它的功能 您可以使用带有 Mask 的 MaskedTestBox000 000 000 000 欲了解更多信息 请参阅文档 http msdn micr
  • 如何区分用户点击链接和页面自动重定向?

    拥有 C WebBrowser control http msdn microsoft com en us library system windows forms webbrowser aspx在我的 WinForms 应用程序中 并意识
  • 获取两个工作日之间的天数差异

    这听起来很简单 但我不明白其中的意义 那么获取两次之间的天数的最简单方法是什么DayOfWeeks当第一个是起点时 如果下一个工作日较早 则应考虑在下周 The DayOfWeek 枚举 http 20 20 5B1 5D 3a 20htt
  • 为什么 Google 测试会出现段错误?

    我是 Google Test 的新手 正在尝试提供的示例 我的问题是 当我引入失败并设置GTEST BREAK ON FAILURE 1 或使用命令行选项 GTest 将出现段错误 我正在考虑这个例子 https code google c
  • 使用接口有什么好处?

    使用接口有什么用 我听说它用来代替多重继承 并且还可以用它来完成数据隐藏 还有其他优点吗 哪些地方使用了接口 程序员如何识别需要该接口 有什么区别explicit interface implementation and implicit
  • 由 IHttpClientFactory 注入时模拟 HttpClient 处理程序

    我创建了一个自定义库 它会自动为依赖于特定服务的 Polly 策略设置HttpClient 这是使用以下方法完成的IServiceCollection扩展方法和类型化客户端方法 一个简化的例子 public static IHttpClie
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 如何检测表单的任何控件的变化?

    如何检测 C 中表单的任何控件的更改 由于我在一个表单上有许多控件 并且如果表单中的任何控件值发生更改 我需要禁用按钮 我正在寻找一些内置函数 事件处理程序 属性 并且不想为此创建自定义函数 不 我不知道任何时候都会触发任何事件any控制表
  • Qt - ubuntu中的串口名称

    我在 Ubuntu 上查找串行端口名称时遇到问题 如您所知 为了在 Windows 上读取串口 我们可以使用以下代码 serial gt setPortName com3 但是当我在 Ubuntu 上编译这段代码时 我无法使用这段代码 se
  • 如何在 32 位或 64 位配置中以编程方式运行任何 CPU .NET 可执行文件?

    我有一个可在 32 位和 64 位处理器上运行的 C 应用程序 我试图枚举给定系统上所有进程的模块 当尝试从 64 位应用程序枚举 32 位进程模块时 这会出现问题 Windows 或 NET 禁止它 我认为如果我可以从应用程序内部重新启动
  • C#:帮助理解 UML 类图中的 <>

    我目前正在做一个项目 我们必须从 UML 图编写代码 我了解 UML 类图的剖析 但我无法理解什么 lt
  • C# HashSet 只读解决方法

    这是示例代码 static class Store private static List
  • 为什么 std::strstream 被弃用?

    我最近发现std strstream已被弃用 取而代之的是std stringstream 我已经有一段时间没有使用它了 但它做了我当时需要做的事情 所以很惊讶听到它的弃用 我的问题是为什么做出这个决定 有什么好处std stringstr
  • 按 Esc 按键关闭 Ajax Modal 弹出窗口

    我已经使用 Ajax 显示了一个面板弹出窗口 我要做的是当用户按 Esc 键时关闭该窗口 这可能吗 如果有人知道这一点或以前做过这一点 请帮助我 Thanks 通过以下链接 您可以通过按退出按钮轻松关闭窗口 http www codepro
  • 如何将 PostgreSql 与 EntityFramework 6.0.2 集成? [复制]

    这个问题在这里已经有答案了 我收到以下错误 实体框架提供程序类型的 实例 成员 Npgsql NpgsqlServices Npgsql 版本 2 0 14 2 文化 中性 PublicKeyToken 5d8b90d52f46fda7 没

随机推荐

  • ubuntu c语言头文件,Ubuntu找不到stdio.h等头文件_安装c库_build-essential安装失败解决...

    最近安装的Ubuntu1804系统 vim gcc都是现安的 用gcc编译时出现找不到头文件情况 于是百度 原来linux类的操作系统上面开发程序 光有了gcc 是不行的 它还需要一个 build essentia 作用是提供编译程序必须软
  • 【无标题】torch.optim.SGD参数详解

    torch optim SGD是PyTorch中实现的Stochastic Gradient Descent SGD 优化器 用于更新神经网络中的参数 以最小化损失函数 从而提高模型的精度 它的一些重要参数如下 lr 学习率 learnin
  • office文档图标显示不正常

    一直用Office2013 前几天用到WPS一个功能 用完后就卸载了 结果电脑中的office文档图标 word excel ppt等 都显示异常 网上查找好久解决了 网址如下 https jingyan baidu com article
  • target_link_libraries 和link_libraries区别

    TARGET LINK LIBRARIES 设置要链接的库文件的名称 语法 TARGET LINK LIBRARIES targetlibrary1
  • 数据结构--并查集

    并查集适用情况 1 有时候 并不关心数据之间的前后关系 也不关心数据的层次关系 一些确定元素只是单纯的聚集在一起 这样的元素聚集集合被称为集合 当希望知道某个数据是否存在一个集合中 或者两个元素是否在同一个集合中时 就需要使用一些集合数据结
  • windows 安装NVM 出现版本切换不成功 问题解决与分析

    1 安装nvm的时候要去删除默认目录下C Program Files nodejs的文件夹 安装完成后也要去检查这个文件夹是不是存在 2 配置环境变量 对应第一步的 2 使用nvm install 版本号 如果能成功下载node 注意说的成
  • FFmpeg部署及操作指南

    什么是FFmpeg FFmpeg是一个开源的跨平台音视频处理工具集 可以用于处理 转换 编辑和流媒体音视频文件 它提供了一组强大的命令行工具 可以实现音视频的解码 编码 封装 过滤 转码等功能 FFmpeg的功能 FFmpeg的功能非常多
  • matlab分类算法函数,MATLAB分类与预测算法函数

    1 glmfit 功能 构建一个广义线性回归模型 使用格式 b glmfit X y distr 根据属性数据X以及每个记录对应的类别数据y构建一个线性回归模型 distr可取值为 binomial gamma inverse gaussi
  • C#系列之值类型与引用类型

    目录 1 变量类型的复习 2 值类型和引用类型的区别 1 变量类型的复习 无符号整形 byte b 1 ushort us 1 uint ui 1 ulong ul 1 有符号整形 sbyte sb 1 short s 1 int i 1
  • LINUX下更改字符编码方式-增加GB2312

    修改local文件 sudo gedit var lib locales supported d local 添加zh CN GB2312字符集 如下 en US UTF 8 UTF 8 zh CN UTF 8 UTF 8 zh CN GB
  • 推荐几个 VS Code 扩展、主题和字体

    前言 工欲善其事 必先利其器 VS Code 作为当前最流行的开源代码编辑器之一 要说它为什么这么受大众喜爱 我觉得一是它现代化的界面 二是它强大的扩展系统 得益于 VS Code 的扩展系统 我们可以给编辑器加上各种 Buff 让它变成自
  • 深度学习经典网络:ShuffleNet 系列网络(ShuffleNet v1)

    ShuffleNet v1 http openaccess thecvf com content cvpr 2018 html Zhang ShuffleNet An Extremely CVPR 2018 paper html tenso
  • 第十四届蓝桥杯模拟赛第二期J题答案(C++代码)

    A题 题面 请找到一个大于 2022 的最小数 这个数转换成二进制之后 最低的 6 个二进制为全为 0 请将这个数的十进制形式作为答案提交 思路 由于最低6位都是0 且 11111000000 2 lt 2048 10 所以选要选取 100
  • 让vs2008与vs2012同时打开同一个项目文件

    在开发过程中 小组开发经常碰到很多人用的ide版本不同 而项目组成员为了参与多个项目 经常安装多个版本的ide 本文主要讲解vs2008与vs2012之间如何在源码管理下同时打开一个项目文件进行开发 本文以c 开发为例 其他语言一样 1 关
  • 并发编程 :Concurrent 用户指南 ( 下 )

    并发编程 Concurrent 用户指南 下 2017 09 04 ImportNew 来源 高广超 www jianshu com p 8cb5d816cb69 锁 Lock java util concurrent locks Lock
  • gradlew 命令说明

    gradlew 命令 快速构建命令 查看所有任务 gradlew tasks all gradlew命令都可以使用简写 例如 gradlew assembleRelease 简写为 gradlew aR 查看项目的依赖都依赖了哪些库 gra
  • Android 3.0 SDK中新增API详解

    Android 3 0 SDK中新增了哪些API呢 我们总结下平板系统honeycomb中的新特性 首先需要澄清的是经过eoeAndroid发现设置模拟器的分辨率到普通WVGA这样的解析度时平板的特性自动消失和Android 2 3没有什么
  • Pytorch 随机种子设置 不可控因素

    为确保模型训练过程中 需要设置模型的随机种子 具体操作如下 主程序 def torch seed seed torch manual seed seed torch cuda manual seed seed torch cuda manu
  • redis三个连接客户端框架的选择:Jedis,Redisson,Lettuce

    Jedis api 在线网址 http tool oschina net uploads apidocs redis clients jedis Jedis html redisson 官网地址 https redisson org red
  • 记录 Libevent的常用功能示例

    介绍 Libevent是开源社区一款高性能的I O框架库 是reactor模式的优秀体现 网上相关资料很多 这篇博文主要以尽量简练的代码实现TcpServer服务器功能 代码覆盖大部分的常用函数接口 通过代码能对Libevent的整体框架