我自己在实现一个http client,使用libevent,遇到一些问题,连接可以建立,但发送http请求后毫无反应。实验了windows和linux两个版本,都是如此。可能还是我使用上的问题。
请给我的决赛文章《Qt Quick 图像处理实例之美图秀秀(附源码下载)》投票,谢谢。
根据网上的例子修改了一下,可以在windows下面跑,没问题了。代码如下:
#include <stdlib.h>
#include <string.h>
#include "event2/event.h"
#include "event2/http.h"
#include "event2/buffer.h"
#include "event2/http_struct.h"
#include "event2/dns.h"
struct download_context{
struct evhttp_uri * uri;
struct event_base * base;
struct evdns_base * dnsbase;
struct evhttp_connection * conn;
struct evhttp_request *req;
struct evbuffer *buffer;
int ok;
};
static void download_callback(struct evhttp_request *req, void *arg);
static int download_renew_request(struct download_context *ctx);
static void download_callback(struct evhttp_request *req, void *arg)
{
struct download_context * ctx = (struct download_context*)arg;
struct evhttp_uri * new_uri = 0;
const char * new_location = 0;
if(!req){
printf("timeout\n");
return;
}
switch(req->response_code)
{
case HTTP_OK:
event_base_loopexit(ctx->base, 0);
break;
case HTTP_MOVEPERM:
case HTTP_MOVETEMP:
new_location = evhttp_find_header(req->input_headers, "Location");
if(!new_location) return;
new_uri = evhttp_uri_parse(new_location);
if(!new_uri)return;
evhttp_uri_free(ctx->uri);
ctx->uri = new_uri;
download_renew_request(ctx);
return;
default:/* failed */
event_base_loopexit(ctx->base, 0);
return;
}
evbuffer_add_buffer(ctx->buffer, req->input_buffer);
ctx->ok = 1;
}
struct download_context * context_new(const char *url)
{
struct download_context * ctx = 0;
ctx = (struct download_context*)calloc(1, sizeof(struct download_context));
ctx->uri = evhttp_uri_parse(url);
if(!ctx->uri) return 0;
ctx->base = event_base_new();
ctx->buffer = evbuffer_new();
ctx->dnsbase = evdns_base_new(ctx->base, 1);
download_renew_request(ctx);
return ctx;
}
void context_free(struct download_context *ctx)
{
if(ctx->conn)
evhttp_connection_free(ctx->conn);
if(ctx->buffer)
evbuffer_free(ctx->buffer);
if(ctx->uri)
evhttp_uri_free(ctx->uri);
free(ctx);
}
static int download_renew_request(struct download_context *ctx)
{
int port = evhttp_uri_get_port(ctx->uri);
if(port == -1) port = 80;
if(ctx->conn) evhttp_connection_free(ctx->conn);
printf("host:%s, port:%d, path:%s\n", evhttp_uri_get_host(ctx->uri), port, evhttp_uri_get_path(ctx->uri));
ctx->conn = evhttp_connection_base_new(ctx->base, ctx->dnsbase, evhttp_uri_get_host(ctx->uri), port );
ctx->req = evhttp_request_new(download_callback, ctx);
evhttp_make_request(ctx->conn, ctx->req, EVHTTP_REQ_GET, evhttp_uri_get_path(ctx->uri));
evhttp_add_header(ctx->req->output_headers, "Host", evhttp_uri_get_host(ctx->uri));
return 0;
}
struct evbuffer *download_url(const char *url)
{
struct download_context * ctx = context_new(url);
if(!ctx) return 0;
event_base_dispatch(ctx->base);
struct evbuffer * retval = 0;
if(ctx->ok)
{
retval = ctx->buffer;
ctx->buffer = 0;
}
context_free(ctx);
return retval;
}
int main(int argc, char **argv)
{
struct evbuffer * data = 0;
if(argc < 2){
printf("usage: %s example.com/\n", argv[0]);
return 1;
}
#ifdef WIN32
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
(void) WSAStartup(wVersionRequested, &wsaData);
#endif
data = download_url(argv[1]);
printf("got %d bytes\n", data ? evbuffer_get_length(data) : -1);
if(data)
{
const unsigned char * joined = evbuffer_pullup(data, -1);
printf("data itself:\n====================\n");
fwrite(joined, evbuffer_get_length(data), 1, stderr);
printf("\n====================\n");
evbuffer_free(data);
}
return 0;
}
需要注意的是,如果从命令行传入网址,比如百度的,必须传入http://www.baidu.com/,否则解析不出来path,下载会失败。
这个例子不是我最终想要的效果,无法控制下载和数据处理过程,它是等下载完成了一次性返回数据。对于大文件,比如几百兆甚至上G的,这种处理策略还不够。我写了一个http处理的模块和一些辅助代码,编译通过,可以运行,但请求发出后对端始终无反应。等我查一查,网上始终找不到libevent http client的例子,有echoserver之类的,就是没有客户端。
研究研究吧,可能是事件的使用上有问题。
分享到:
相关推荐
libevent,多线程,client,serverlibevent多线程, 参考mariotcp 参考http://blog.csdn.net/i_am_jojo/article/details/7587838流程图
linux下使用libevent实现断网重连的tcp客户端,自动检测tcp连接断开,断开后能自动重连;如果连不上服务器,则一直尝试连接服务器,直至连接成功。
libevent http服务器客户端最简版本,libevent库里面带的sample,太过臃肿,当我们简单使用或测试时太过于麻烦,现在提供一个简单的版本
像libevent, libev, and libuv , libhv提供具有非阻塞IO和计时器的事件循环,但具有更简单的api和更丰富的协议。 :sparkles: 特征 跨平台(Linux,Windows,Mac,Solaris) EventLoop(IO,计时器,空闲) TCP ...
像libevent, libev, and libuv , libhv提供具有非阻塞IO和计时器的事件循环,但具有更简单的api和更丰富的协议。 产品特点 跨平台(Linux,Windows,Mac,Solaris) 事件循环(IO,计时器,空闲) ENABLE_IPV6 ...
websocket::WebSocketClient ws (loop); ws.on_connection = [](websocket::WebSocket* ws, const websocket::HttpResponse* res) { ws-> send ({ 16 , 0 , 15 , 0 }); ws-> send ( " echo hello " ); res-> ...
LiteSpeed QUIC(LSQUIC)库自述文件描述LiteSpeed QUIC(LSQUIC)库是服务器和客户端的QUIC和HTTP / 3功能的开源实现。 此发行版中的大多数代码... 该示例程序使用libevent提供事件循环。构建BoringSSL 未打包BoringS
我们还重新编写了代码,并用libevent2替换了libhttpd(多年以来一直未使用过) 表现因为libevent2支持epoll,所以apfree-wifidog的性能要比原始wifidog更好,基准目录中有一些基准数据可以证明这一点HTTP重定向...
支持TCP、UDP、Unix、SSL, 内置HTTP/WebSocket/Async Redis/Async TCP Client, 并支持自定义数据包解析,从而实现任何应用层协议。 SSL/reuse_port/cluster dispatcher/工作进程平滑重启等特性, 单个进程中可实现多...
"client" => [ // '172.17.0.5:8089', '127.0.0.1:8089' ], "key" => "test", // 需要登录跳转的登录地址 "login_url" => "http://www.baidu.com", // 是否自动跳去登录 "autoredirectloginurl" => false, ...
Libwebsockets is a simple-to-use, MIT-license, pure C library providing client and server for http/1, http/2, websockets, MQTT and other protocols in a security-minded, lightweight, configurable, ...
1、因为openstack软件包超过50M,上传受到限制所以分成了两部分下载,请搜索“openstack安装包(一)”,或者到http://download.csdn.net/?ref=toolbar_logo 搜索该资源,下载完后合并packages文件夹即可完整安装,...
Mir client ............................. no Qt Sql: SQL item models ........................ yes Qt Widgets: GTK+ ................................... no Styles ................................. ...