异步I/O库-libuv介绍

1.简介

libuv是一个跨平台的支持事件驱动的异步I/O的库,使开发者可以以非阻塞的方式执行文件I/O操作、网络通信、子进程管理等。

libuv的主要特点包括:

  • 事件循环:libuv有一个基于事件循环的模型,它不断地轮询事件,并在事件发生时调用相应的回调函数。
  • 异步I/O:libuv提供了异步文件I/O和网络I/O的接口,使得开发者可以执行I/O操作而不阻塞主线程。
  • 线程池:libuv使用线程池来处理一些不能以非阻塞方式执行的I/O操作,如文件系统操作在某些操作系统上。
  • DNS解析:libuv提供了异步DNS解析的接口。
  • 高分辨率时钟:libuv提供了高精度的时间测量接口。

libuv的使用通常涉及以下几个步骤:

  • 初始化:使用uv_loop_init初始化事件循环。
  • 创建句柄:根据需要创建相应的句柄,如TCP句柄、UDP句柄等。
  • 启动事件循环:使用uv_run启动事件循环。
  • 关闭句柄:在不再需要句柄时,使用uv_close关闭句柄。
  • 清理资源:在程序结束时,使用uv_loop_close清理事件循环。

2.常用接口介绍

uv_loop_t - 事件循环

  • uv_loop_init(uv_loop_t*):初始化一个事件循环。
  • uv_run(uv_loop_t*,uv_run_mode):开始运行事件循环。uv_run_mode 可以是 UV_RUN_DEFAULT、UV_RUN_ONCE 或UV_RUN_NOWAIT。
  • uv_loop_close(uv_loop_t*):关闭事件循环并释放相关资源。

uv_handle_t - 句柄基类

  • uv_handle_size(uv_handle_type):返回特定类型句柄的大小。
  • uv_close(uv_handle_t*, uv_close_cb):关闭一个句柄并释放资源。当句柄关闭完成后,会调用
    uv_close_cb 回调函数。

uv_tcp_t - TCP 句柄

  • uv_tcp_init(uv_loop_t*, uv_tcp_t*):初始化一个 TCP 句柄。
  • uv_tcp_bind(uv_tcp_t*, const struct sockaddr*, unsigned int):将 TCP句柄绑定到指定的地址和端口。
  • uv_tcp_connect(uv_connect_t*, uv_tcp_t*, const struct sockaddr*, uv_connect_cb):异步连接到服务器。连接成功或失败时会调用 uv_connect_cb 回调函数。

uv_udp_t - UDP 句柄

  • uv_udp_init(uv_loop_t*, uv_udp_t*):初始化一个 UDP 句柄。
  • uv_udp_bind(uv_udp_t*, const struct sockaddr*, unsigned int):将 UDP句柄绑定到指定的地址端口。
  • uv_udp_recv_start(uv_udp_t*, uv_alloc_cb,uv_udp_recv_cb):开始接收 UDP 数据。uv_alloc_cb 用于分配接收缓冲区,uv_udp_recv_cb用于处理接收到的数据。

uv_timer_t - 定时器

  • uv_timer_init(uv_loop_t*, uv_timer_t*):初始化一个定时器。
  • uv_timer_start(uv_timer_t*, uv_timer_cb, uint64_t,uint64_t):启动定时器。uv_timer_cb 是定时器超时时的回调函数,uint64_t 参数指定第一次超时时间和重复间隔。
  • uv_timer_stop(uv_timer_t*):停止定时器。

uv_work_t - 工作线程

  • uv_queue_work(uv_loop_t*, uv_work_t*, uv_work_cb,
    uv_after_work_cb):将工作推送到 libuv 的线程池中执行。uv_work_cb
    是在线程池中执行的工作函数,uv_after_work_cb 是工作完成后在事件循环线程中调用的回调函数。

uv_process_t - 进程

  • uv_spawn(uv_loop_t*, uv_process_t*, constuv_process_options_t*):创建一个新进程。
  • uv_process_kill(uv_process_t*, int):发送信号到进程。

uv_fs_t - 文件系统操作

  • uv_fs_open(uv_loop_t*, uv_fs_t*, const char*, int, int,uv_fs_cb):异步打开文件。
  • uv_fs_read(uv_loop_t*, uv_fs_t*, uv_file, const uv_buf_t*, unsigned int, int64_t, uv_fs_cb):异步读取文件。
  • uv_fs_write(uv_loop_t*, uv_fs_t*, uv_file, const uv_buf_t*, unsigned int, int64_t, uv_fs_cb):异步写入文件。

3.环境搭建

下载地址:https://github.com/libuv/libuv
下载完成,进行解压,然后使用cmake编译。
configure->Generate->Open Project
在这里插入图片描述
生成库如下图所示:
在这里插入图片描述
拷贝头文件和lib、dll目录到demo程序,然后配置visual sudio环境。具体步骤请看前面文章配置。

4.示例

TCP服务端:

#include <iostream>
#include <string>
extern "C"
{
#include "uv.h"
}void on_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {buf->base = (char*)malloc(suggested_size);buf->len = suggested_size;
}void on_read(uv_stream_t* client, ssize_t nread, const uv_buf_t* buf) {if (nread < 0) {// 如果读取错误或连接已关闭,释放内存并关闭客户端uv_close((uv_handle_t*)client, NULL);free(buf->base);return;}std::string message = "Hello, World!\n";uv_write_t* req = (uv_write_t*)malloc(sizeof(uv_write_t));uv_buf_t wrbuf = uv_buf_init((char*)message.c_str(), message.length());uv_write(req, client, &wrbuf, 1, [](uv_write_t* req, int status) {free(req);if (status < 0) {std::cerr << "Write error: " << uv_strerror(status) << std::endl;}});// 释放内存free(buf->base);
}void on_new_connection(uv_stream_t* server, int status) {if (status < 0) {std::cerr << "New connection error: " << uv_strerror(status) << std::endl;return;}uv_tcp_t* client = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));uv_tcp_init(uv_default_loop(), client);if (uv_accept(server, (uv_stream_t*)client) == 0) {uv_read_start((uv_stream_t*)client, on_alloc, on_read);}else {uv_close((uv_handle_t*)client, NULL);}
}int main() 
{uv_tcp_t server;uv_tcp_init(uv_default_loop(), &server);struct sockaddr_in addr;uv_ip4_addr("0.0.0.0", 8080, &addr);uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0);int r = uv_listen((uv_stream_t*)&server, 128, on_new_connection);if (r) {std::cerr << "Listen error: " << uv_strerror(r) << std::endl;return 1;}std::cout << "Listening on port 8080..." << std::endl;uv_run(uv_default_loop(), UV_RUN_DEFAULT);return 0;
}

TCP客户端:

void on_connect(uv_connect_t* req, int status) {if (status < 0) {std::cerr << "Connect error: " << uv_strerror(status) << std::endl;return;}// 连接成功,发送数据uv_stream_t* stream = req->handle;std::string message = "Hello, Server!\n";uv_write_t* write_req = (uv_write_t*)malloc(sizeof(uv_write_t));uv_buf_t buf = uv_buf_init((char*)message.c_str(), message.length());uv_write(write_req, stream, &buf, 1, [](uv_write_t* req, int status) {free(req);if (status < 0) {std::cerr << "Write error: " << uv_strerror(status) << std::endl;}});
}void on_read(uv_stream_t* client, ssize_t nread, const uv_buf_t* buf) {if (nread < 0) {// 如果读取错误或连接已关闭,释放内存并关闭客户端uv_close((uv_handle_t*)client, NULL);free(buf->base);return;}// 打印接收到的数据std::cout.write(buf->base, nread);// 释放内存free(buf->base);
}int main() {uv_tcp_t* socket = (uv_tcp_t*)malloc(sizeof(uv_tcp_t));uv_tcp_init(uv_default_loop(), socket);struct sockaddr_in dest;uv_ip4_addr("127.0.0.1", 8080, &dest);uv_connect_t* connect_req = (uv_connect_t*)malloc(sizeof(uv_connect_t));uv_tcp_connect(connect_req, socket, (const struct sockaddr*)&dest, on_connect);// 开始读取数据uv_read_start((uv_stream_t*)socket, [](uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {buf->base = (char*)malloc(suggested_size);buf->len = suggested_size;}, on_read);std::cout << "Connecting to server..." << std::endl;uv_run(uv_default_loop(), UV_RUN_DEFAULT);// 清理资源free(socket);free(connect_req);return 0;
}

5.更多参考

libVLC 专栏介绍-CSDN博客

Qt+FFmpeg+opengl从零制作视频播放器-1.项目介绍_qt opengl视频播放器-CSDN博客

QCharts -1.概述-CSDN博客

网络库-libevent介绍

网络库-libcurl介绍

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【2024年电工杯数学建模竞赛】选题分析+A题B题完整思路+代码分享

.2024年电工杯数学建模AB题选题思路 比赛开始第一时间在下面的资料裙分享&#xff1a; 点击链接加入群聊【2024数维杯数学建模ABC题资料汇总】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kBwulH5tSN2X7iLXzZHAJqRk9sYnegd0y&authKey2TSsuOgqXZQ%2FvTX4R59…

Java面试八股之Java中有哪些原子类,原理是什么

Java中有哪些原子类&#xff0c;原理是什么 AtomicInteger 和 AtomicLong&#xff1a; 用于对整数&#xff08;int&#xff09;和长整数&#xff08;long&#xff09;进行原子操作。 原理&#xff1a;它们内部封装了一个整型或长整型变量&#xff0c;并通过使用Unsafe类提供…

手机如何下载短视频到本地:成都鼎茂宏升文化传媒公

手机如何下载短视频到本地 ​随着移动互联网的迅猛发展&#xff0c;短视频已经成为人们生活中不可或缺的一部分。从娱乐、学习到社交&#xff0c;短视频以其短小精悍、内容丰富的特点&#xff0c;吸引了大量用户的关注。然而&#xff0c;有时我们可能希望将喜欢的短视频保存到…

jspXMl标记语言基础

1.打开命令框进入数据库 打开eclipse创建需要连接的项目 粘贴驱动程序 查看驱动器 使用sql的包 int代表个 conlm代表列名 <%page import"java.sql.ResultSet"%> <%page import"java.sql.Statement"%> <%page import"java.sql.Connect…

基于Java+SpringBoot+Mybaties-plus+Vue+elememt 驾校管理系统 设计与实现

一.项目介绍 系统角色&#xff1a;管理员、驾校教练、学员 管理员&#xff1a; 个人中心&#xff1a;修改密码以及个人信息修改 学员管理&#xff1a;维护学员信息&#xff0c;维护学员成绩信息 驾校教练管理&#xff1a;驾校教练信息的维护 驾校车辆管理&…

如何找到MySQL中存储引擎所对应的表空间并且打开?

在上节课我们学习了数据库&#xff08;MySQL&#xff09;进阶&#xff1a;存储引擎&#xff0c;有不少同学产生疑惑&#xff0c;到底要怎么找到表空间并且打开啊&#xff1f;这节课我们就来探讨。 首先&#xff0c;根据这个路径&#xff1a;C:\ProgramData\MySQL\MySQL Server…

程序在银河麒麟系统下实现开机自启及创建桌面快捷方式

目录 1. 机器环境说明 2. 程序开机自启动设置 2.桌面快捷方式设置 3. 附加说明 1. 机器环境说明 机器安装的银河麒麟操作系统属性如下&#xff1a; 2. 程序开机自启动设置 第1步&#xff1a;编写一个脚本,用于自动化启动&#xff0c;为便于后文描述&#xff0c;该脚本名称…

pikachu靶场通关之暴力破解token防爆破

这里写pikachu靶场token防爆破的第二种解法 用python脚本跑&#xff0c;下面是代码 import requests from bs4 import BeautifulSoup# url填自己的url url http://localhost:8086/pikachu-master/vul/burteforce/bf_token.php # 取出账号字典里的值&#xff0c;1.txt就是账号…

Google play开发者账号被封了,内购的款还可以提出来吗?

在Google paly上架过程中&#xff0c;很多开发者通过内购的方式来获取收益或变现。不过&#xff0c;有时会因为违反了Google play相关规定或其它原因&#xff0c;导致应用下架&#xff0c;账号被封&#xff0c;在这样的情况下&#xff0c;开发者们最关心的问题之一就是&#xf…

1. 杜克大学官方宣布2027届新生画像什么是vue关键特点核心概念简单示例生态系统

目录 1. 杜克大学官方宣布2027届新生画像 什么是vue 关键特点 核心概念 简单示例 生态系统 1. 杜克大学官方宣布2027届新生画像 杜克大学校报《The Chronicle》已连续第七年对杜克大学的一年级新生进行深入调查&#xff0c;探讨该群体家庭受教育背景、家庭收入水平以及…

放松冥想心得体会|流静冥想

冥想&#xff0c;古已有之。昔人云&#xff1a;“静以修身”&#xff0c;非虚言也。放松心灵&#xff0c;乃通往内在平和之路。社恐者&#xff0c;常困于喧嚣之境&#xff0c;心难宁静。然&#xff0c;以冥想之法&#xff0c;可徐徐引导&#xff0c;渐归宁谧。 坐于幽室&#x…

搭载全新升级viaim AI,讯飞会议耳机Pro 2首销价1399元起

2024年5月15日&#xff0c;人工智能硬件公司未来智能发布了讯飞会议耳机Pro 2、iFLYBUDS 2以及Kit 2三款旗舰新品&#xff0c;为用户带来全新升级的viaim AI&#xff0c;也为AIGC智能耳机树立了新标杆。 在发布会上&#xff0c;未来智能CEO马啸表示&#xff1a;在AIGC领域&…