lib-zo,C語言另一個協程庫,dns協程化, gethostbyname
另一個 C 協程庫 https://blog.csdn.net/eli960/article/details/146802313
本協程庫 支持 DNS查詢 協程化.
禁用所有 UDP 協程化
zvar_coroutine_disable_udp = 1;
禁用 53 端口的UDP 協程化
zvar_coroutine_disable_udp_53 = 1;
例子
// 包含協程相關的頭文件
#include "coroutine.h"// 包含解析器相關的頭文件
#include <resolv.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>// 定義并發實例的數量
static int instances = 10;
// 定義測試類型
static int test_type = 0;/*** @brief 執行域名查詢測試的協程函數* * @param arg 傳入的參數,為要查詢的域名* @return void* 總是返回 0*/
static void *foo(void *arg)
{// 將參數轉換為字符串類型,即要查詢的域名const char *name = (char *)arg;// 用于存儲 DNS 查詢結果的緩沖區char answer[1024+1];
#ifdef res_nquery// 定義解析器狀態結構體struct __res_state state;// 如果測試類型為 2,則初始化解析器狀態if (test_type == 2) {res_ninit(&state);}
#endif// 循環執行 10 次查詢操作for (int i = 0; i < 10; i++) {// 在第 3 次和第 6 次循環時暫停 1 秒if ((i == 3) || (i == 6)) {sleep(1);}// 如果測試類型為 0,使用 gethostbyname 進行查詢if (test_type == 0) {// 調用 gethostbyname 函數進行域名查詢struct hostent *hp = gethostbyname(name);if (hp) {// 查詢成功,打印域名及其官方名稱printf("%s: %s\n", name, hp->h_name);} else {// 查詢失敗,打印未找到信息printf("%s: not found\n", name);}}// 如果測試類型為 1,使用 res_query 進行查詢if (test_type == 1) {// 調用 res_query 函數進行 DNS 查詢int ret = res_query(name, C_IN, T_A, (unsigned char *)answer, 1024);// 打印查詢結果printf("res_query %s: %d\n", name, ret);}
#ifdef res_nquery// 如果測試類型為 2,使用 res_nquery 進行查詢if (test_type == 2) {// 調用 res_nquery 函數進行 DNS 查詢int ret = __res_nquery(&state, name, C_IN, T_A, (unsigned char *)answer, 1024);// 打印查詢結果printf("res_nquery %s: %d\n", name, ret);}
#endif}
#ifdef res_nquery// 如果測試類型為 2,關閉解析器狀態if (test_type == 2) {res_nclose(&state);}
#endif// 完成一個實例的查詢,實例數量減 1instances--;return 0;
}/*** @brief 監控實例數量,當所有實例完成后通知協程停止的函數* * @param arg 傳入的參數,未使用* @return void* 總是返回 0*/
static void *foo2(void *arg)
{// 當還有未完成的實例時,持續等待while(instances) {sleep(1);}// 所有實例完成后,再等待 1 秒sleep(1);// 通知協程基礎框架停止運行zcoroutine_base_stop_notify(0);return 0;
}/*** @brief 初始化函數,處理命令行參數并輸出使用說明* * @param argc 命令行參數的數量* @param argv 命令行參數數組* @return int 初始化成功返回 1,失敗返回 0*/
static int _init(int argc, char **argv)
{// 輸出程序的使用說明printf("USAGE: \n%s domain1 domain2 [ test_type ] [ disable_udp]\n", argv[0]);printf(" test_type:\n");printf(" 0\t\t # gethostbyname(default)\n");printf(" 1\t\t # res_query\n");
#ifdef res_nqueryprintf(" 2\t\t # res_nquery\n");
#elseprintf(" 2\t\t # res_nquery, unsupported\n");
#endifprintf(" disable_udp:\n");printf(" udp\t\t # disable all udp coroutine swap\n");printf(" 53\t\t # disable udp(53) coroutine swap\n");// 如果命令行參數少于 3 個,說明輸入不完整,返回 0if (argc < 3) {return 0;}printf("\n");// 標記是否顯示了測試類型信息int type_show = 0;// 處理第 3 個及以后的命令行參數for (int i = 3; i < argc; i++) {const char *s = argv[i];if (!strcmp(s, "0")) {// 測試類型為 0,使用 gethostbyname 進行查詢printf("######## test gethostbyname\n");type_show = 1;test_type = 0;} else if (!strcmp(s, "1")) {// 測試類型為 1,使用 res_query 進行查詢printf("######## test req_query\n");type_show = 1;test_type = 1;} else if (!strcmp(s, "2")) {// 測試類型為 2,使用 res_nquery 進行查詢printf("######## test req_nquery\n");type_show = 1;test_type = 2;} else if (!strcmp(s, "udp")) {// 禁用所有 UDP 協程交換zvar_coroutine_disable_udp = 1;printf("######## disable all udp\n");} else if (!strcmp(s, "53")) {// 禁用 UDP 端口 53 的協程交換zvar_coroutine_disable_udp_53 = 1;printf("######## disable udp(53)\n");} else {// 未知參數,輸出提示信息printf("######## unknown %s\n", s);}}// 如果未指定測試類型,使用默認的 gethostbyname 測試if (type_show == 0) {printf("######## test gethostbyname, default\n");}
#ifndef res_nquery// 如果系統不支持 res_nquery,輸出提示信息printf("######## res_nquery unsupported in your system\n");
#endifprintf("\n");return 1;
}/*** @brief 程序入口函數* * @param argc 命令行參數的數量* @param argv 命令行參數數組* @return int 程序退出狀態碼*/
int main(int argc, char **argv)
{// 調用初始化函數,如果初始化失敗,直接返回 0if (_init(argc, argv) == 0) {return 0;}// 初始化協程基礎框架zcoroutine_base_init();// 創建協程進行域名查詢for (int i = 0; i < instances/2; i++) {zcoroutine_go(foo, argv[1], 0);zcoroutine_go(foo, argv[2], 0);}// 創建監控協程zcoroutine_go(foo2, 0, 0);// 啟動協程基礎框架運行zcoroutine_base_run();// 銷毀協程基礎框架zcoroutine_base_fini();return 0;
}