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;
}