基本环境

使用版本为libevent-2.1.5,目前为beta版,其中evhttp和旧版区别在于新增了如下接口

// 设置回调函数,在包头读取完成后回调
void evhttp_request_set_header_cb (struct evhttp_request *, int(*cb)(struct evhttp_request *, void *))// 设置回调函数,在body有数据返回后回调
void evhttp_request_set_chunked_cb (struct evhttp_request *, void(*cb)(struct evhttp_request *, void *))
  • 1
  • 2
  • 3
  • 4
  • 5

这样的好处是可以在合适的时机回调我们注册的回调函数,比如下载1G的文件,在之前的版本只有下载完成后才会回调,现在每下载一部分数据就会回调一次,让上层应用更加灵活,尤其在http代理时,可以做到边下载边回复

2.1.5版本的完整接口文档详见http://www.wangafu.net/~nickm/libevent-2.1/doxygen/html/http_8h.html

请求流程

http客户端使用到的接口函数及请求流程如下

  1. 初始化event_base和evdns_base

    struct event_base *event_base_new(void);
    struct evdns_base * evdns_base_new(struct event_base *event_base, int initialize_nameservers);
    • 1
    • 2
  2. 创建evhttp_request对象,并设置回调函数,这里的回调函数是和数据接收相关的

    struct evhttp_request *evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg);
    void evhttp_request_set_header_cb(struct evhttp_request *, int (*cb)(struct evhttp_request *, void *));
    void evhttp_request_set_chunked_cb(struct evhttp_request *, void (*cb)(struct evhttp_request *, void *));
    void evhttp_request_set_error_cb(struct evhttp_request *, void (*)(enum evhttp_request_error, void *));
    • 1
    • 2
    • 3
    • 4
  3. 创建evhttp_connection对象,并设置回调函数,这里的回调函数是和连接状态相关的

    struct evhttp_connection *evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase, const char *address, unsigned short port);
    void evhttp_connection_set_closecb(struct evhttp_connection *evcon,void (*)(struct evhttp_connection *, void *), void *);
    • 1
    • 2
    • 3
    • 4
  4. 有选择的向evhttp_request添加包头字段

    int evhttp_add_header(struct evkeyvalq *headers, const char *key, const char *value);
    • 1
  5. 发送请求

    int evhttp_make_request(struct evhttp_connection *evcon,struct evhttp_request *req,enum evhttp_cmd_type type, const char *uri);
    • 1
    • 2
    • 3
  6. 派发事件

    int event_base_dispatch(struct event_base *);
    

完整代码

#include "event2/http.h"
#include "event2/http_struct.h"
#include "event2/event.h"
#include "event2/buffer.h"
#include "event2/dns.h"
#include "event2/thread.h"#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <sys/queue.h>
#include <event.h>void RemoteReadCallback(struct evhttp_request* remote_rsp, void* arg)
{event_base_loopexit((struct event_base*)arg, NULL);
} int ReadHeaderDoneCallback(struct evhttp_request* remote_rsp, void* arg)
{fprintf(stderr, "< HTTP/1.1 %d %s\n", evhttp_request_get_response_code(remote_rsp), evhttp_request_get_response_code_line(remote_rsp));struct evkeyvalq* headers = evhttp_request_get_input_headers(remote_rsp);struct evkeyval* header;TAILQ_FOREACH(header, headers, next){fprintf(stderr, "< %s: %s\n", header->key, header->value);}fprintf(stderr, "< \n");return 0;
}void ReadChunkCallback(struct evhttp_request* remote_rsp, void* arg)
{char buf[4096];struct evbuffer* evbuf = evhttp_request_get_input_buffer(remote_rsp);int n = 0;while ((n = evbuffer_remove(evbuf, buf, 4096)) > 0){fwrite(buf, n, 1, stdout);}
}void RemoteRequestErrorCallback(enum evhttp_request_error error, void* arg)
{fprintf(stderr, "request failed\n");event_base_loopexit((struct event_base*)arg, NULL);
}void RemoteConnectionCloseCallback(struct evhttp_connection* connection, void* arg)
{fprintf(stderr, "remote connection closed\n");event_base_loopexit((struct event_base*)arg, NULL);
}int main(int argc, char** argv)
{if (argc != 2){printf("usage:%s url", argv[1]);return 1;}char* url = argv[1];struct evhttp_uri* uri = evhttp_uri_parse(url);if (!uri){fprintf(stderr, "parse url failed!\n");return 1;}struct event_base* base = event_base_new();if (!base){fprintf(stderr, "create event base failed!\n");return 1;}struct evdns_base* dnsbase = evdns_base_new(base, 1);if (!dnsbase){fprintf(stderr, "create dns base failed!\n");}assert(dnsbase);struct evhttp_request* request = evhttp_request_new(RemoteReadCallback, base);evhttp_request_set_header_cb(request, ReadHeaderDoneCallback);evhttp_request_set_chunked_cb(request, ReadChunkCallback);evhttp_request_set_error_cb(request, RemoteRequestErrorCallback);const char* host = evhttp_uri_get_host(uri);if (!host){fprintf(stderr, "parse host failed!\n");return 1;}int port = evhttp_uri_get_port(uri);if (port < 0) port = 80;const char* request_url = url;const char* path = evhttp_uri_get_path(uri);if (path == NULL || strlen(path) == 0){request_url = "/";}printf("url:%s host:%s port:%d path:%s request_url:%s\n", url, host, port, path, request_url);struct evhttp_connection* connection =  evhttp_connection_base_new(base, dnsbase, host, port);if (!connection){fprintf(stderr, "create evhttp connection failed!\n");return 1;}evhttp_connection_set_closecb(connection, RemoteConnectionCloseCallback, base);evhttp_add_header(evhttp_request_get_output_headers(request), "Host", host);evhttp_make_request(connection, request, EVHTTP_REQ_GET, request_url);event_base_dispatch(base);return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123

编译

g++ http_client.cpp -I/opt/local/libevent-2.1.5/include -L/opt/local/libevent-2.1.5/lib -levent -g -o http_client

运行示例,这里只打印了包头字段

 $ ./http_client http://www.qq.com >/dev/null
< HTTP/1.1 200 OK
< Server: squid/3.4.3
< Content-Type: text/html; charset=GB2312
< Cache-Control: max-age=60
< Expires: Fri, 05 Aug 2016 08:48:31 GMT
< Date: Fri, 05 Aug 2016 08:47:31 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< Connection: Transfer-Encoding
< 

libevent evhttp学习——http客户端相关推荐

  1. libevent evhttp学习——http服务端

    http服务端相对客户端要简单很多,我们仍旧使用libevent-2.1.5版本,服务端接口和2.0版本没有区别 基本流程 http服务端使用到的借口函数及流程如下 创建event_base和evht ...

  2. 【libevent】libevent库学习总结(一)——基础

    libevent库学习总结(一)--基础 一.基础 1.1. 介绍 Libevent是一个用于开发可伸缩网络服务器的事件通知库.Libevent API提供了一种机制来执行回调函数,当某个特定事件发生 ...

  3. WPF学习开发客户端软件-任务助手(下 2015年2月4日代码更新)

    时光如梭,距离第一次写的 WPF学习开发客户端软件-任务助手(已上传源码)  已有三个多月,期间我断断续续地对该项目做了优化.完善等等工作,现在重新向大家介绍一下,希望各位可以使用,本软件以实用性为主 ...

  4. webService学习4:客户端调用服务端的代码

    1 服务器端sayHello变化了一点,代码如下 @WebService public class HelloWSImpl implements HelloWS {public String sayH ...

  5. 学习云客户端安装流程

    学习云客户端安装流程 通过网盘链接下载好文件后,通过接下来的三部来完成安装操作 安装客户端 解压镜像文件 配置BIOS 虚拟化与安全启动 下面是两个配置的链接,可以先配置起来,也可以安装完再配置 wi ...

  6. 【国产数据库】GBase学习⑤ - gsql 客户端连接工具

    [国产数据库]GBase学习⑤ - gsql 客户端连接工具 gsql介绍 gsql使用方式 DBeaver客户端工具配置 gsql介绍 GBase 8c 客户端工具是gsql.类似于MySQL的my ...

  7. 学习OCS客户端定制

    一步一步学习OCS2007(一)--如何定制在线状态?(转自:http://www.cnblogs.com/invinboy ) OCS 2007(即Microsoft Office Communic ...

  8. openfire学习4---android客户端聊天开发之聊天功能开发

    前面我们已经把服务器搭建完成,并且在客户端实现了登录了. 和我们使用的QQ一样,想一想,登录成功之后呢?肯定是要有一个好友列表,通过这个列表,我们可以选择我们需要聊天的好友. 这里我们先研究下 xmp ...

  9. Android HIDL 介绍学习之客户端调用

    应上一篇文章Android HIDL 介绍学习_Super Jang的博客-CSDN博客_安卓hidl读者的要求,本文更新客户端调用方法. hidl的客户端调用相比服务端的实现要简单很多,本次我们通过 ...

最新文章

  1. 使用wsimport生成本地调用代码
  2. 循环语句——7月23日
  3. 计算机网络与通信pdf谢希仁_考研刷题资料谢希仁《计算机网络》(第7版)配套题库【考研真题精选(部分视频讲解)+章节题库】...
  4. java 根据当前时间获得一周日期
  5. 锁相放大器sr830_各位谁会用Stanford SR830啊,我都快被这个锁相放大器折腾死了!!!!-北京搜狐焦点...
  6. python c4.5完整代码_python实现c4.5/Id3自我练习
  7. python求解二次规划_Python二次规划和线性规划使用实例
  8. python-zip方法
  9. 比特币技术公司创始人:ICO是一场被骗子玩弄的网络泡沫
  10. JQuery Ajax 解析
  11. Redis在游戏服务器中的应用
  12. python基础-菜鸟世界 -python基础---set
  13. 根据自身工作经验总结的一个工作问题解决思路
  14. [20170516]nvl与非NULL约束.txt
  15. redis zset底层数据结构
  16. ps怎么撤销参考线_Photoshop120条新手必备技巧
  17. WiFi通信模块框图
  18. Learn Git Branching 学习笔记(关于origin和它的周边——Git远程仓库高级操作篇)
  19. Intel opreation mode
  20. 英特尔Skylake处理器全面入驻Google Compute Engine

热门文章

  1. adjacent angle_GRE/GMAT 数学之平面几何
  2. STM32----摸石头过河系列(五)
  3. C4D插件:Springy for Mac 动​​画对象添加重叠动作插件
  4. 1.5编程基础之循环控制 34 求阶乘的和
  5. 正则表达式加参数匹配
  6. flutter引入高德地图_Flutter笔记-调用原生IOS高德地图sdk
  7. Qt文档阅读笔记-RadioButton的基本使用
  8. HTTP中CORS跨域请求的实现(C++|Qt框架实现)
  9. Java基础入门笔记-使用变量并打印
  10. 计算特征矩阵及哈希值(含OpenCV代码)