Windows下VS2015 编译libevent及使用,编译错误提示

  1. 下载地址:http://libevent.org/ ,下载版本:libevent-2.1.11-stable.tar.gz

  2. 解压, 目录为...\libevent-2.1.11-stable

  3. 进入文件夹,找到minheap-internal.h,修改头文件#include "stdint.h"

  4. 如果编译X64位程序 需修改makefile文件 LIBFLAGS的值后面追加/MACHINE:X64 如果要加调试信息,可以在 CFLAGS中加入/Zi,32位加调试选项是 CFLAGS中加/ZI,当然要调整优化选项/Ox

  5. 执行命令:nmake /f Makefile.nmake

  6. 编译成功 命令成功执行后就会生产三个lib文件:libevent.lib libevent_core.lib libevent_extras.lib表示编译成功

  7. 创建工程

  8. 拷贝头文件,相关的头文件包括三个地方:(1)libevent-2.0.12-stable\include\*   (2)libevent-2.0.12-stable\WIN32-Code\*    (3)libevent-2.0.12-stable\*.h

    把这些头文件都复制一下放到一个单独的include文件夹中方便管理。

  9. 拷贝库文件 libevent编译完成后,生成的相关静态库文件包括三个:libevent.lib libevent_core.lib libevent_extras.lib,可以单独建立一个lib文件夹存放;

  10. 添加链接库 附件依赖项,添加 ws2_32.lib wsock32.lib libevent.lib libevent_core.lib libevent_extras.lib

  11. 如果编译提示 

    错误 2 error LNK2019: 无法解析的外部符号 __imp__CryptAcquireContextA@20,该符号在函数 _arc4_seed_win32 中被引用

    错误 3 error LNK2019: 无法解析的外部符号 __imp__CryptGenRandom@12,该符号在函数 _arc4_seed_win32 中被引用

    需引用AdvAPI32.lib

  12. 测试demo

    #include <stdio.h>
    #define WIN32_LEAN_AND_MEAN
    
    #include <stdlib.h>
    //#include <unistd.h>     //for getopt, fork
    #include <string.h>     //for strcat
    //for struct evkeyvalq
    //#include <sys/queue.h>
    #include <event.h>
    //for http
    //#include <evhttp.h>
    #include <event2/http.h>
    #include <event2/http_struct.h>
    #include <event2/http_compat.h>
    #include <event2/util.h>
    #include <signal.h>
    #include "cJSON.h"
    
    #define MYHTTPD_SIGNATURE   "MoCarHttpd v0.1"
    
    //处理模块
    void httpd_handler(struct evhttp_request *req, void *arg) {
        char output[2048] = "\0";
        char tmp[1024];
    
        //获取客户端请求的URI(使用evhttp_request_uri或直接req->uri)
        const char *uri;
        uri = evhttp_request_uri(req);
    #if 0
        sprintf(tmp, "uri=%s\n", uri);//  /data?cmd=new...
        strcat(output, tmp);
    #endif
    
        sprintf(tmp, "uri=%s\n", req->uri);
        strcat(output, tmp);
    
        //decoded uri
        char *decoded_uri;
        decoded_uri = evhttp_decode_uri(uri);
        sprintf(tmp, "decoded_uri=%s\n", decoded_uri);// /data?cmd= newFile ...
        strcat(output, tmp);
    
        //http://127.0.0.1:8080/username=gailun&passwd=123123
    
        //解析URI的参数(即GET方法的参数)
        struct evkeyvalq params;//key ---value, key2--- value2//  cmd --- newfile  fromId == 0
        //将URL数据封装成key-value格式,q=value1, s=value2
        evhttp_parse_query(decoded_uri, &params);
    
        //得到q所对应的value
        sprintf(tmp, "username=%s\n", evhttp_find_header(&params, "username"));
        strcat(output, tmp);
        //得到s所对应的value
        sprintf(tmp, "passwd=%s\n", evhttp_find_header(&params, "passwd"));
        strcat(output, tmp);
    
        free(decoded_uri);
    
        //获取POST方法的数据
        char *post_data = (char *) EVBUFFER_DATA(req->input_buffer);
        sprintf(tmp, "post_data=%s\n", post_data);
        strcat(output, tmp);
    
    
        /*
           具体的:可以根据GET/POST的参数执行相应操作,然后将结果输出
           ...
         */
        //入库
    
    
    
        /* 输出到客户端 */
    
        //HTTP header
        evhttp_add_header(req->output_headers, "Server", MYHTTPD_SIGNATURE);
        evhttp_add_header(req->output_headers, "Content-Type", "text/plain; charset=UTF-8");
        evhttp_add_header(req->output_headers, "Connection", "close");
    
        //输出的内容
        struct evbuffer *buf;
        buf = evbuffer_new();
        evbuffer_add_printf(buf, "It works!\n%s\n", output);
    
        //将封装好的evbuffer 发送给客户端
        evhttp_send_reply(req, HTTP_OK, "OK", buf);
    
        evbuffer_free(buf);
    
    }
    
    //处理模块
    void login_handler(struct evhttp_request *req, void *arg) {
    
        printf("got connection ");
    
        char request_data[4096] = {0};
    
        //获取POST方法的数据
        size_t post_size = EVBUFFER_LENGTH(req->input_buffer);
        char *post_data = (char *) EVBUFFER_DATA(req->input_buffer);
        memcpy(request_data, post_data, post_size);
        printf("post_data = [%s], len =%ld\n", post_data, post_size);
    
    
    
        char username[256] = {0};
        char password[256] = {0};
        char isDriver[10] = {0};
        /*
           具体的:可以根据GET/POST的参数执行相应操作,然后将结果输出
           ...
         */
    
        /*
    
           ====给服务端的协议====
            http://ip:port/login [json_data]
            {
                username: "gailun",
                password: "123123",
                driver:   "yes"
            }
         *
         *
         * */
        cJSON *root = cJSON_Parse(request_data);
        
    	if (root == NULL)
    	{
    		/* 输出到客户端 */
    
    		//HTTP header
    		evhttp_add_header(req->output_headers, "Server", MYHTTPD_SIGNATURE);
    		evhttp_add_header(req->output_headers, "Content-Type", "text/plain; charset=UTF-8");
    		evhttp_add_header(req->output_headers, "Connection", "close");
    		//将封装好的evbuffer 发送给客户端
    		//输出的内容
    		struct evbuffer *buf;
    		buf = evbuffer_new();
    		evbuffer_add_printf(buf, "%s", "auth error");
    
    		//将封装好的evbuffer 发送给客户端
    		evhttp_send_reply(req, HTTP_BADREQUEST, "error", buf);
    
    		evbuffer_free(buf);
    		return;
    	}
    
        cJSON* username_obj = cJSON_GetObjectItem(root, "username");
        strcpy(username, username_obj->valuestring);
    
    
        cJSON* password_obj = cJSON_GetObjectItem(root, "password");
        strcpy(password, password_obj->valuestring);
    
        cJSON* isDriver_obj = cJSON_GetObjectItem(root, "driver");
        strcpy(isDriver, isDriver_obj->valuestring);
    
        printf("username = %s, password = %s, isDriver = %s\n", username, password, isDriver);
        cJSON_Delete(root);
        printf("----\n");
    
    
        //查询数据库 得到查询结果
    
    
        //给前段回复一个响应结果
        cJSON*response_root = cJSON_CreateObject();
        
        cJSON_AddStringToObject(response_root, "result", "ok");
    
        char *response_str = cJSON_Print(response_root);
    
    
    
    
        /* 输出到客户端 */
    
        //HTTP header
        evhttp_add_header(req->output_headers, "Server", MYHTTPD_SIGNATURE);
        evhttp_add_header(req->output_headers, "Content-Type", "text/plain; charset=UTF-8");
        evhttp_add_header(req->output_headers, "Connection", "close");
    
        //输出的内容
        struct evbuffer *buf;
        buf = evbuffer_new();
        evbuffer_add_printf(buf, "%s", response_str);
    
        //将封装好的evbuffer 发送给客户端
        evhttp_send_reply(req, HTTP_OK, "OK", buf);
    
        evbuffer_free(buf);
    
        cJSON_Delete(response_root);
        free(response_str);
    }
    
    
    void show_help() {
        char *help = "http://localhost:8080\n"
            "-l <ip_addr> interface to listen on, default is 0.0.0.0\n"
            "-p <num>     port number to listen on, default is 1984\n"
            "-d           run as a deamon\n"
            "-t <second>  timeout for a http request, default is 120 seconds\n"
            "-h           print this help and exit\n"
            "\n";
        fprintf(stderr,"%s",help);
    }
    
    
    int main(int argc, char *argv[]) {
        //自定义信号处理函数
    	WSADATA wsaData;
    	DWORD Ret;
    	if ((Ret = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
    	{
    		printf("WSAStartup failed with error %d\n", Ret);
    		return -1;
    	}
    
        //默认参数
        char *httpd_option_listen = "0.0.0.0";
        int httpd_option_port = 7777;
        int httpd_option_daemon = 0;
        int httpd_option_timeout = 120; //in seconds
    
        获取参数
        //int c;
        //while ((c = getopt(argc, argv, "l:p:dt:h")) != -1) {
        //    switch (c) {
        //        case 'l' :
        //            httpd_option_listen = optarg;
        //            break;
        //        case 'p' :
        //            httpd_option_port = atoi(optarg);
        //            break;
        //        case 'd' :
        //            httpd_option_daemon = 1;
        //            break;
        //        case 't' :
        //            httpd_option_timeout = atoi(optarg);
        //            break;
        //        case 'h' :
        //        default :
        //            show_help();
        //            exit(EXIT_SUCCESS);
        //    }
        //}
    
        判断是否设置了-d,以daemon运行
        //if (httpd_option_daemon) {
        //    pid_t pid;
        //    pid = fork();
        //    if (pid < 0) {
        //        perror("fork failed");
        //        exit(EXIT_FAILURE);
        //    }
        //    if (pid > 0) {
        //        //生成子进程成功,退出父进程
        //        exit(EXIT_SUCCESS);
        //    }
        //}
    
    
        /* 使用libevent创建HTTP Server */
    
        //初始化event API
        event_init();
    
        //创建一个http server
        struct evhttp *httpd;
    
        httpd = evhttp_start(httpd_option_listen, httpd_option_port);
    
        evhttp_set_timeout(httpd, httpd_option_timeout);
    
        //也可以为特定的URI指定callback
        evhttp_set_cb(httpd, "/", httpd_handler, NULL);
        evhttp_set_cb(httpd, "/login", login_handler, NULL);
    
        //循环处理events
        event_dispatch();
    
        evhttp_free(httpd);
    
        return 0;
    }
    


     

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值