[libuv] libuv学习

From: https://www.mobibrw.com/2016/3490

libuv 是重写了下libev,封装了windows和unix的差异性。
libuv的特点
非阻塞TCP套接字 socket?
非阻塞命名管道
UDP
定时器
子进程 fork?
通过 uv_getaddrinfo实现异步DNS
异步文件系统API uv_fs_*
高分辨率时间 uv_hrtime
正在运行程序路径查找 uv_exepath
线程池调度 uv_queue_work
TTY控制的ANSI转义代码 uv_tty_t
文件系统事件支持 inotify ReadDirectoryChangesW kqueue 马上回支持 uv_fs_event_t
进程间的IPC与套接字共享 uv_write2

事件驱动的风格:程序关注/发送事件,在事件来临时给出反应。
系统编程中,一般都是在处理I/O,而IO的主要障碍是网络读取,在读取的时候是阻塞掉的。标准的解决方案是使用多线程,每一个阻塞的IO操作被分配到一个线程。当线程block,处理器调度处理其他线程。
libuv使用了另一个方案,异步。操作系统提供了socket的事件,即使用socket,监听socket事件即可。

libuv简单使用 创建一个loop,关闭loop。
#include <stdio.h>
#include <stdlib.h>
#include <uv.h>

int main()
{
uv_loop_t *loop = malloc(sizeof(uv_loop_t));
uv_loop_init(loop);

printf("hello, libuv");

uv_run(loop, UV_RUN_DEFAULT);

uv_loop_close(loop);
free(loop);

return 0;
}

如果只需要一个loop的话,调用uv_default_loop就可以了。
tips:Nodejs中使用了这个loop作为主loop。
uv_loop_t *loop = uv_default_loop();

uv_run(loop, UV_RUN_DEFAULT);

uv_loop_close(loop);

Error
初始化或同步函数,会在执行失败是返回一个负数,可以通过uv_strerror、uv_err_name获得这个错误的名字和含义
I/O函数的回调函数会被传递一个nread参数,如果nread小于0,也代表出现了错误。

Handle & Request
libuv的工作建立在事件的监听上,通常通过handle来实现,handle中uv_TYPE_t中的type指定了handle监听的事件。
在uv.h中可以找到handle和request的定义
/* Handle types. */
typedef struct uv_loop_s uv_loop_t;
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t;
typedef struct uv_udp_s uv_udp_t;
typedef struct uv_pipe_s uv_pipe_t;
typedef struct uv_tty_s uv_tty_t;
typedef struct uv_poll_s uv_poll_t;
typedef struct uv_timer_s uv_timer_t;
typedef struct uv_prepare_s uv_prepare_t;
typedef struct uv_check_s uv_check_t;
typedef struct uv_idle_s uv_idle_t;
typedef struct uv_async_s uv_async_t;
typedef struct uv_process_s uv_process_t;
typedef struct uv_fs_event_s uv_fs_event_t;
typedef struct uv_fs_poll_s uv_fs_poll_t;
typedef struct uv_signal_s uv_signal_t;

/* Request types. */
typedef struct uv_req_s uv_req_t;
typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
typedef struct uv_getnameinfo_s uv_getnameinfo_t;
typedef struct uv_shutdown_s uv_shutdown_t;
typedef struct uv_write_s uv_write_t;
typedef struct uv_connect_s uv_connect_t;
typedef struct uv_udp_send_s uv_udp_send_t;
typedef struct uv_fs_s uv_fs_t;
typedef struct uv_work_s uv_work_t;

/* None of the above. */
typedef struct uv_cpu_info_s uv_cpu_info_t;
typedef struct uv_interface_address_s uv_interface_address_t;
typedef struct uv_dirent_s uv_dirent_t;

handle是持久化的对象。在异步操作中,相应的handle有许多关联的request。
request是短暂性的,通常只维持一个回调的时间,一般对应handle的一个IO操作。request用来在初始函数和回调函数中传递上下文。
例如uv_udp_t代表了一个udp的socket,每一个socket的写入完成后,都有一个uv_udp_send_t被传递。

handle的设置
uv_TYPE_init(uv_loop_t*, uv_TYPE_t);

一个idle handle的使用例子 观察下它的生命周期
#include <stdio.h>
#include <uv.h>

int counter = 0;

void wait_for(uv_idle_t * handle)
{
counter++;

if (counter > 10e6)
{
uv_idle_stop(handle);
}
}

int main()
{
uv_idle_t idler;

uv_idle_init(uv_default_loop(), &idler);
uv_idle_start(&idler, wait_for);

printf("Idle......");

uv_run(uv_default_loop(), UV_RUN_DEFAULT);

uv_loop_close(uv_default_loop());

return 0;
}

参数传递
handle和request都有一个data域,用来传递信息。uv_loop_t也有一个相似的data域。

文件系统
简单的文件读写是通过uv_fs_*函数族和与之相关的uv_fs_t结构体完成的。
系统的文件操作是阻塞的,所以libuv在线程池中调用这些函数,最后通知loop。

如果没有指定回调函数,文件操作是同步的,return libuv error code。
异步在传入回调函数时调用,return 0。

获得文件描述符
int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb);
关闭文件描述符
int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
回调函数
void callback(uv_fs_t* req);
还有uv_fs_read uv_fs_write uv_fs_t构成了基本的文件操作

流操作使用uv_stream_t,比基本操作方便不少
uv_read_start uv_read_stop uv_write
流操作可以很好的配合pipe使用
pipe相关函数
uv_pipe_init uv_pipe_open uv_close

文件事件
uv_fs_event_t uv_fs_event_init uv_fs_event_start

网络
uv_ip4_addr ip为 0.0.0.0表示绑定所有接口 255.255.255.255是一个广播地址,意味着数据将往所有的子网接口发送,端口号0表示由操作系统随机分配一个端口
tcp
TCP是面向连接的字节流协议,因此基于libuv的stream实现
uv_tcp_t
服务器端创建流程
uv_tcp_init 建立tcp句柄
uv_tcp_bind 绑定
uv_listen 建立监听,当有新的连接到来时,激活调用回调函数
uv_accept 接收链接
使用stream处理数据以及与客户端通信

客户端
客户端比较简单,只需要调用uv_tcp_connect

udp
UDP是不可靠连接,libuv基于uv_udp_t和uv_udp_send_t
udp的流程与tcp类似

libuv提供了一个异步的DNS解决方案,提供了自己的getaddrinfo
配置好主机参数addrinfo后使用uv_getaddrinfo即可

调用uv_interface_addresses获得系统的网络信息

未完待续。

来源:http://luohaha.github.io/Chinese-uvbook/source/introduction.html

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

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

相关文章

elemnt的Table 表格使用注意事项

elemnt的Table 表格使用注意事项 1、修改数据 <template slot-scope"scope"><el-button size"mini" clickupdatePassword(scope.row)>修改密码</el-button><el-button size"mini" clickresetPassword(scope.row)>重置密…

px、em、rem、vm、vw 、vh、vmin 、vmax区分

Px表示“绝对尺寸”&#xff08;并非真正的绝对&#xff09;&#xff0c;实际上就是css中定义的像素&#xff08;此像素与设备的物理像素有一定的区别&#xff0c;后续详细说明见文末说明1&#xff09;&#xff0c;利用px设置字体大小及元素宽高等比较稳定和精确。Px的缺点是其…

Class.forName()用法详解

Class.forName()用法详解 标签&#xff1a; classjvmjdbc数据库documentationjava2012-03-29 09:39 40414人阅读 评论(8) 收藏 举报分类&#xff1a;Java考古学&#xff08;74&#xff09; 主要功能 Class.forName(xxx.xx.xx)返回的是一个类 Class.forName(xxx.xx.xx)的作用是要…

[poco] 访问数据库

From: https://blog.csdn.net/hl2015222050145/article/details/52335422?utm_sourceblogxgwz6 poco访问数据基本步骤&#xff1a; a. 创建会话(session) b. 从DB中读写数据 c. 使用statements d. 使用容器&#xff08;Collection&#xff09; (数据&#xff0c;集合...) …

应对不良网络文化的技术之一——网络信息抽取技术

1 引言 2008年1月17日&#xff0c;中国互联网络信息中心(CNNIC)发布了《第21次中国互联网络发展状况统计报告》[1]&#xff0c;报告显示&#xff1a; (1) 截至2007年12月&#xff0c;网民数已增至2.1亿人。中国网民数增长迅速&#xff0c;比2007年6月增加4800万人&…

最安全的js类型检测

众所周知js内置的类型检测机制不可靠&#xff0c;比如typeof操作符&#xff0c;对于正则和数组检测时返回值都是object&#xff0c; 而使用instanceof检测类型时&#xff0c;虽然可以对正则和数组正常验证&#xff0c;但验证undefined会报错&#xff0c;还有对于Symbol无法验证…

HBuilder完成webApp入门(2)

一、HBuilder的下载地址&#xff1a;http://www.dcloud.io/&#xff0c;点击那个“DownLoad”就可以 了 二、假设一切顺利&#xff0c;启动HBuilder后&#xff0c;大家会看到如下的界面 点击新建移动APP&#xff1a; 接下来就会弹出一个选择模板的对话框&#xff1a; 默认的模板…

js防篡改对象之不可扩展对象

const person {name: 啦啦德玛西亚}console.log(Object.isExtensible(person))//true//使用Object.preventExtensions()可以将对象修改为不可扩展对象&#xff0c;无法再给对象添加属性和方法Object.preventExtensions(person)//使用Object.isExtensible()方法可以确定对象是否…

高可用集群 heartbeatv1实例

——————— 高可用集群的简单配置 ————————地址规划 主节点&#xff1a;HA1 172.16.21.13 hostname node2.magedu.com备节点&#xff1a; HA2 172.16.21.14 hostname node1.magedu.comVIP 172.16.21.9前提工作1&#xff0c;配置主机名 hostname保证uname …

你知道“拉黑”、“关注”、“点赞”、“转发”、“分享到朋友圈”等英语咋说吗?

From: https://www.sohu.com/a/220161051_559507 “分享到朋友圈”等英语咋说吗&#xff1f; Mini apps 小程序 小程序”&#xff08;mini apps&#xff09;是一个不需要下载安装就可使用的应用&#xff08;apps that can be accessed without downloading&#xff09;&#x…

C#进化史

C#进化史 C#进化史从数据类型看C#演化C# 1写的产品类C# 强类型集合——解决限制1和2c# 自动属性——解决限制3c# 4 命名实参C# 1~C# 4的演变历程排序C# 1——提供一个IComparer实现C# 2——泛型比较器C# 3——Lambda表达式、扩展方法C# 1~C# 3简化排序的历程查询集合C# 1——循…

防篡改对象之密封对象

const person {name: 啦啦德玛西亚}console.log(Object.isExtensible(person))// trueconsole.log(Object.isSealed(person))// false// 使用Object.seal()将对象修改为密封对象// 密封对象不可扩展&#xff0c;而且已有成员的[[Configurable]]特性将被设置为false// 意味着不…

配套自测连载(三)

接上期(答案已给出)本期是专门针对《深入理解计算机网络》图书第4章而编写的10道计算机网络体系架构中的物理层技术自测题&#xff0c;可以检验你对本章的学习效果。把你的答案直接写在评论中即可&#xff0c;笔者将在每期发表10天后给出正确答案。本书是国内最通俗、最系统的计…

[json] JSON for Modern C++

有幸能接触到这个&#xff0c;这是我遇到的使用最方便的json了&#xff0c;效率没研究过&#xff01; 简单了使用了下&#xff0c;感觉非常好用&#xff0c;记录下&#xff1a; 要使用这个json&#xff0c;只需要使用json.hpp就行&#xff0c;放入自己的工程里&#xff0c;但…

面向对象的需求分析方法

面向对象的需求分析方法 面向对象的需求分析方法的核心是利用面向对象的概念和方法为软件需求建造模型。它包含面向对象风格的图形语言机制和用于指导需求分析的面向对象方法学。 面向对象的思想最初起源于 20世纪 60年代中期的仿真程序设计语言Simula67。20世纪80年代初出现的…

js防篡改对象之冻结对象

const person {name: 啦啦德玛西亚,_job: 无业}Object.defineProperty(person, job, {get: function() {return this._job},set: function(newValue) {this._job newValue}})console.log(Object.isFrozen(person))// false//使用Object.freeze()将对象修改为冻结对象&#xf…

libinject的编译

libinject是一个Android进程注入实例&#xff0c;其下载地址为&#xff1a;http://download.csdn.net/download/ljhzbljhzb/3680780 libinject的编译需要NDK开发环境&#xff0c;在NDK安装成功之后&#xff0c;可以先将其自带的实例中的HelloJni导入到eclipse中&#xff0c;编译…

Boost - 序列化 (Serialization)

From: https://blog.csdn.net/zj510/article/details/8105408 程序开发中&#xff0c;序列化是经常需要用到的。像一些相对高级语言&#xff0c;比如JAVA, C#都已经很好的支持了序列化&#xff0c;那么C呢&#xff1f;当然一个比较好的选择就是用Boost&#xff0c;这个号称C准…

Linux Supervisor 守护进程基本配置

supervisor:C/S架构的进程控制系统&#xff0c;可使用户在类UNIX系统中监控、管理进程。常用于管理与某个用户或项目相关的进程。 组成部分supervisord&#xff1a;服务守护进程supervisorctl&#xff1a;命令行客户端Web Server&#xff1a;提供与supervisorctl功能相当的WEB操…

ES6使用object的is()方法比较两个值

此前js比较两个值是否相等时&#xff0c;一般使用 或 符号&#xff0c;我之前倾向使用后者&#xff0c;因为可以避免比较时触发强制类型转换&#xff0c;但某些情况使用 依然有问题&#xff0c;比如再比较NaN NaN时&#xff0c;返回的是false&#xff0c;需要使用isNaN()才能…