日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[libuv] libuv学习

發布時間:2023/12/9 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [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

總結

以上是生活随笔為你收集整理的[libuv] libuv学习的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。