日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

libevent evhttp学习——http客户端

發布時間:2025/3/15 编程问答 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 libevent evhttp学习——http客户端 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

基本環境

使用版本為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客戶端使用到的接口函數及請求流程如下

  • 初始化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
  • 創建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
  • 創建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
  • 有選擇的向evhttp_request添加包頭字段

    int evhttp_add_header(struct evkeyvalq *headers, const char *key, const char *value);
    • 1
  • 發送請求

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

    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客户端的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。