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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 创建任务方法原型在workflow中所有的客户端任务都放在`WFTaskFactory`工厂类中+ `url:`请求的http url+ `redirect_max:`表示最大重定向次数。如果在请求过程中遇到重定向,该参数指定了最多允许重定向的次数。+ `retry_max`:表示最大重试次数。如果请求失败,该参数指定了最多可以重试的次数。+ `callback`:这是一个回调函数的指针,用于处理请求的响应。原型为`using http_callback_t = std::function

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

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

创建并启动http任务

示例

#include <workflow/WFFacilities.h>
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<void (WFHttpTask *)>;说白了,就是一个参数为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);
}

代码解析

  1. 需要说明的是,所有工厂函数不会返回失败,所以不用担心task为空指针,哪怕是url不合法。一切错误都在callback再处理。
  2. httpTask->get_req()函数得到任务的request,默认是GET方法,HTTP/1.1长连接。框架会自动加上request_uri,Host等。
  3. 框架会在发送前根据需要自动加上Content-Length或Connection这些http header。用户也可以通过add_header_pair()方法添加自己的header。
  4. 关于http消息的更多接口,可以在HttpMessage.h中查看。
  5. httpTask->start()启动任务,非阻塞,并且不会失败。之后callback必然会在被调用。因为异步的原因,start()以后显然不能再用httpTask指针了。
  6. 为了让示例尽量简单,start()之后调用pause()防止程序退出,用户需要Ctrl-C结束程序。

处理http抓取结果

示例代码

首先,先看一眼示例代码

#include <workflow/WFFacilities.h>
#include <workflow/HttpMessage.h>
#include <workflow/HttpUtil.h>

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对象,对requestresponseheader进行扫描。获取响应头,在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头部。

目录
相关文章
|
2月前
|
NoSQL 网络协议 Linux
Redis的实现一:c、c++的网络通信编程技术,先实现server和client的通信
本文介绍了使用C/C++进行网络通信编程的基础知识,包括创建socket、设置套接字选项、绑定地址、监听连接以及循环接受和处理客户端请求的基本步骤。
57 6
|
2月前
|
算法 C++ 容器
C++标准库(速查)总结
C++标准库(速查)总结
79 6
|
2月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
112 10
|
17天前
|
数据采集 JSON 测试技术
Grequests,非常 Nice 的 Python 异步 HTTP 请求神器
在Python开发中,处理HTTP请求至关重要。`grequests`库基于`requests`,支持异步请求,通过`gevent`实现并发,提高性能。本文介绍了`grequests`的安装、基本与高级功能,如GET/POST请求、并发控制等,并探讨其在实际项目中的应用。
27 3
|
2月前
|
网络协议
Lua中实现异步HTTP请求的方法
Lua中实现异步HTTP请求的方法
|
2月前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
79 5
|
2月前
|
存储 自然语言处理 程序员
C++常用基础知识—STL库(1)
C++常用基础知识—STL库(1)
70 1
|
2月前
|
JSON 网络协议 网络安全
详解新一代 HTTP 请求库:httpx
详解新一代 HTTP 请求库:httpx
107 1
|
3月前
|
编译器 API C语言
超级好用的C++实用库之跨平台实用方法
超级好用的C++实用库之跨平台实用方法
44 6
|
3月前
|
安全 C++
超级好用的C++实用库之环形内存池
超级好用的C++实用库之环形内存池
65 5
下一篇
DataWorks