C++异步网络库workflow入门教程(1)HTTP任务

C++异步网络库workflow入门教程(1)HTTP任务

如果觉得小弟写的可以,请给一个点赞+关注支持

workFlow c++异步网络库编译教程与简介

创建并启动http任务

示例

#include

int main(){

WFHttpTask * httpTask = WFTaskFactory::create_http_task("http://baidu.com",0,0,0);

protocol::HttpRequest *req = httpTask->get_req();

req->add_header_pair("Accept","*/*");

req->add_header_pair("User-Agent","myHttpTask");

req->set_header_pair("Connection","close");

httpTask->start();

pause();

}

创建任务方法原型

在workflow中所有的客户端任务都放在WFTaskFactory工厂类中,

url:请求的http url

redirect_max:表示最大重定向次数。如果在请求过程中遇到重定向,该参数指定了最多允许重定向的次数。

retry_max:表示最大重试次数。如果请求失败,该参数指定了最多可以重试的次数。

callback:这是一个回调函数的指针,用于处理请求的响应。原型为using http_callback_t = std::function;说白了,就是一个参数为Task本身,没有返回值的函数。这个callback可以传NULL,表示无需callback。我们一切任务的callback都是这个风格。

#include "workflow/WFTaskFactory.h"

class WFTaskFactory

{

public:

static WFHttpTask *create_http_task(const std::string& url,

int redirect_max,

int retry_max,

http_callback_t callback);

}

代码解析

需要说明的是,所有工厂函数不会返回失败,所以不用担心task为空指针,哪怕是url不合法。一切错误都在callback再处理。

httpTask->get_req()函数得到任务的request,默认是GET方法,HTTP/1.1,长连接。框架会自动加上request_uri,Host等。

框架会在发送前根据需要自动加上Content-Length或Connection这些http header。用户也可以通过add_header_pair()方法添加自己的header。

关于http消息的更多接口,可以在HttpMessage.h中查看。

httpTask->start()启动任务,非阻塞,并且不会失败。之后callback必然会在被调用。因为异步的原因,start()以后显然不能再用httpTask指针了。

为了让示例尽量简单,start()之后调用pause()防止程序退出,用户需要Ctrl-C结束程序。

处理http抓取结果

示例代码

首先,先看一眼示例代码

#include

#include

#include

void callback(WFHttpTask *httpTask){

//在回调函数中,可以获取任务的所有信息的

protocol::HttpRequest *req = httpTask->get_req();

protocol::HttpResponse *resp = httpTask->get_resp();

int state = httpTask->get_state();

int error = httpTask->get_error();

switch (state)

{

case WFT_STATE_SYS_ERROR:

fprintf(stderr,"system error: %s\n", strerror(error));

break;

case WFT_STATE_DNS_ERROR:

fprintf(stderr,"dns error: %s\n", gai_strerror(error));

break;

case WFT_STATE_SUCCESS:

break;

}

if(state != WFT_STATE_SUCCESS){

fprintf(stderr,"Failed\n");

return;

}

else{

fprintf(stderr,"Success!\n");

}

fprintf(stderr,"request\r\n %s %s %s\r\n", req->get_method(),

req->get_request_uri(),

req->get_http_version());

//使用迭代器来遍历首部字段

std::string name;

std::string value;

protocol::HttpHeaderCursor reqCursor(req);

while(reqCursor.next(name,value)){

fprintf(stderr,"%s:%s\r\n",name.c_str(),value.c_str());

}

fprintf(stderr,"\r\n");

fprintf(stderr,"response\r\n %s %s %s\r\n", resp->get_http_version(),

resp->get_status_code(),

resp->get_reason_phrase());

protocol::HttpHeaderCursor respCursor(resp);

while(respCursor.next(name,value)){

fprintf(stderr,"%s:%s\r\n",name.c_str(),value.c_str());

}

fprintf(stderr,"\r\n");

//print response body

const void *body;

size_t size;

resp->get_parsed_body(&body,&size);

//get_parsed_body方法会修改指针变量body的指向

fwrite(body,1,size,stderr);

}

//异步+回调

int main(){

signal(SIGINT,sigHandler);

WFHttpTask * httpTask = WFTaskFactory::create_http_task("http://baidu.com",0,0,callback);

protocol::HttpRequest *req = httpTask->get_req();

req->add_header_pair("Accept","*/*");

req->add_header_pair("User-Agent","myHttpTask");

req->set_header_pair("Connection","close");

httpTask->start();

pause();

}

代码解析

在这个callback里,httpTask就是我们通过工厂产生的httpTask。

httpTask->get_req()得到任务的request,是HttpMessage类的派生。

req->get_method():获取请求方法,这里返回GET

req->get_request_uri() :请求url,这里返回http://baidu.com

req->get_http_version():http版本,默认HTTP1.1

httpTask->get_resp()得到任务的response,这个和request区别不大,都是HttpMessage的派生。

resp->get_parsed_body(&body,&size)获取http响应体,通过传入void*的地址,也就是传入二级指针以及size参数地址,,内部修改void*指针的指向以及size值,将其指向内部隐藏的响应体和大小,

这个调用得到的是原始的http body,不解码chunk编码。如需解码chunk编码,可使用HttpUtil.h里的

httpTask->get_state()与httpTask->get_error()分别获得任务的运行状态和错误码。

WFT_STATE_SUCCESS表示运行正常,没有异常

WFT_STATE_DNS_ERROR表示出现dns错误,一般是url写错了

WFT_STATE_SYS_ERROR表示出现系统错误,

通过HttpHeaderCursor对象,对request和response的header进行扫描。获取响应头,在HttpUtil.h可以看到Cursor的定义。

class HttpHeaderCursor

{

public:

HttpHeaderCursor(const HttpMessage *message);

...

void rewind();

...

bool next(std::string& name, std::string& value);

bool find(const std::string& name, std::string& value);

...

};

相信这个cursor在使用上应该不会有什么疑惑。

HttpChunkCursor。 另外需要说明的是,find()接口会修改cursor内部的指针,即使用过find()过后如果仍然想对header进行遍历,需要通过rewind()接口回到cursor头部。

相关推荐

iPad (第 4 代) 怎么升级到 iPadOS 11 及以上版本
上海365彩票

iPad (第 4 代) 怎么升级到 iPadOS 11 及以上版本

📅 07-01 👁️ 7553
北京3D打印服务资讯
26365

北京3D打印服务资讯

📅 01-21 👁️ 5077
全面解析电信和联通双线接入方案
上海365彩票

全面解析电信和联通双线接入方案

📅 11-03 👁️ 4863
SD卡、T卡检测工具:保障存储性能与数据安全
365bet亚洲足球赛

SD卡、T卡检测工具:保障存储性能与数据安全

📅 02-16 👁️ 4749
2024年API监控完全指南
365bet亚洲足球赛

2024年API监控完全指南

📅 08-13 👁️ 5579
专门回收旧手机的人,拿旧手机做什么,原来暗藏着猫腻,看完赶紧提醒家人