异步I/O库-libuv介绍

ops/2024/9/22 22:47:26/

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.ppmy.cn/ops/41654.html

相关文章

【实战selenium框架下在爱企查爬取企业的历史变更信息】文末附Google浏览器和驱动的下载

代码如下 # 导入包 import random import time from tkinter import filedialog import tkinter as tk import xlrd import os import datetime import csv from selenium import webdriver from selenium.webdriver import Keys from selenium.webdriver.common.by import By…

亚马逊自养号测评策略:提升店铺产品权重的秘诀

对于卖家而言&#xff0c;拥有一款爆款产品无疑是获得流量的关键&#xff0c;同时它也能显著提升店铺的销量。因此&#xff0c;大部分卖家都热衷于学习如何打造爆款产品的策略&#xff0c;特别是对于那些致力于经营自己店铺的卖家来说&#xff0c;掌握这一技巧对于店铺的成功运…

2022 年高教社杯全国大学生数学建模竞赛-C 题 古代玻璃制品的成分分析与鉴别详解+聚类模型Python代码源码

前言 简单介绍一下我自己&#xff1a;博主专注建模四年&#xff0c;参与过大大小小数十来次数学建模&#xff0c;理解各类模型原理以及每种模型的建模流程和各类题目分析方法。参与过十余次数学建模大赛&#xff0c;三次美赛获得过二次M奖一次H奖&#xff0c;国赛二等奖。**提…

JAVA实验项目(二): 抽象类、接口的定义与使用

实验项目二 抽象类、接口的定义与使用 Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&…

python常见数据的存取

python数据的存取 python数据的存取数据的保存3.1.1 保存list3.1.2 保存Dict3.1.3 保存Set3.1.4 保存Dataframe3.1.5 保存Matrix 3.2 数据的读取3.2.1 读取txt文件中的数据3.2.2 读取excel文件中的数据3.2.3 读取csv文件中的数据3.2.4 读取stata文件中的数据3.2.5 读取R文件中的…

银川业务外包选邦芒 助力企业有效控制用工成本

业务外包是企业战略的一部分&#xff0c;旨在通过专业化和灵活性提升企业的核心竞争力。银川邦芒人力通过其专业的人员管理和规范化的操作流程&#xff0c;帮助企业将重复性和非核心的业务流程外包出去&#xff0c;从而简化企业的用工流程&#xff0c;降低人员管理成本&#xf…

Leetcode39.组合总和

文章目录 题目描述解题思路重复子集剪枝 代码 题目 参考题解 题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返…

ros_control hardware_interface硬件接口

目录 硬件接口 设置新机器人 使用现有接口 创建机器人专用界面 资源管理 硬件接口 ROS 控制使用硬件接口与可用的 ROS 控制器之一结合使用&#xff0c;向硬件发送 ( write() ) 命令并从中接收 ( read() ) 关节状态。 截至撰写本文时可用的硬件接口列表&#xff08;通过…