lib-zo,C语言另一个协程库,dns协程化, gethostbyname

lib-zo,C语言另一个协程库,dns协程化, gethostbyname

另一个 C 协程库 https://blog.csdn.net/eli960/article/details/146802313

本协程库 支持 DNS查询 协程化.

禁用所有 UDP 协程化

c 复制代码
zvar_coroutine_disable_udp = 1;

禁用 53 端口的UDP 协程化

c 复制代码
zvar_coroutine_disable_udp_53 = 1;

例子

c 复制代码
// 包含协程相关的头文件
#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
    // 完成一个实例的查询,实例数量减 1
    instances--;
    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_nquery
    printf("    2\t\t # res_nquery\n");
#else
    printf("    2\t\t # res_nquery, unsupported\n");
#endif
    printf("  disable_udp:\n");
    printf("    udp\t\t # disable all udp coroutine swap\n");
    printf("    53\t\t # disable udp(53) coroutine swap\n");

    // 如果命令行参数少于 3 个,说明输入不完整,返回 0
    if (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");
#endif
    printf("\n");
    return 1;
}

/**
 * @brief 程序入口函数
 * 
 * @param argc 命令行参数的数量
 * @param argv 命令行参数数组
 * @return int 程序退出状态码
 */
int main(int argc, char **argv)
{
    // 调用初始化函数,如果初始化失败,直接返回 0
    if (_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;
}
相关推荐
云之兕12 分钟前
Java内存模型详解:堆、栈、方法区
java·开发语言·jvm
@蓝莓果粒茶16 分钟前
LeetCode第131题_分割回文串
开发语言·前端·算法·leetcode·职场和发展·c#·.net
nlog3n40 分钟前
Java 代理模式 详解
java·开发语言·代理模式
lly2024061 小时前
抽象工厂模式
开发语言
一只小松许️1 小时前
Rust切片、结构体、枚举
开发语言·rust
陳長生.1 小时前
JAVA EE_多线程-初阶(二)
java·开发语言·jvm·java-ee
QTX187302 小时前
常见的 JavaScript 框架和库
开发语言·javascript·ecmascript
爽帅_2 小时前
【C++】STL库_stack_queue 的模拟实现
开发语言·c++
maizeman1262 小时前
R语言——获取数据1
开发语言·r语言·数据读取·内置数据集
。。。9042 小时前
C++中,应尽可能将引用形参声明为const
开发语言·c++