C++异步网络库workflow入门教程(1)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头部。

目录
相关文章
|
1月前
|
存储 并行计算 前端开发
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术(二)
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术
39 1
|
1月前
|
数据安全/隐私保护 C++ 容器
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术(一)
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术
47 0
|
15天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
39 6
|
30天前
|
存储 算法 Java
【C/C++ 线程池设计思路】 深入探索线程池设计:任务历史记录的高效管理策略
【C/C++ 线程池设计思路】 深入探索线程池设计:任务历史记录的高效管理策略
74 0
|
1天前
|
存储 缓存 开发框架
Flutter的网络请求:使用Dart进行HTTP请求的技术详解
【4月更文挑战第26天】了解Flutter网络请求,本文详述使用Dart进行HTTP请求
|
3天前
|
JSON 测试技术 API
Python的Api自动化测试使用HTTP客户端库发送请求
【4月更文挑战第18天】在Python中进行HTTP请求和API自动化测试有多个库可选:1) `requests`是最流行的选择,支持多种请求方法和内置JSON解析;2) `http.client`是标准库的一部分,适合需要低级别控制的用户;3) `urllib`提供URL操作,适用于复杂请求;4) `httpx`拥有类似`requests`的API,提供现代特性和异步支持。根据具体需求选择,如多数情况`requests`已足够。
9 3
|
10天前
|
网络协议 Java API
深度剖析:Java网络编程中的TCP/IP与HTTP协议实践
【4月更文挑战第17天】Java网络编程重在TCP/IP和HTTP协议的应用。TCP提供可靠数据传输,通过Socket和ServerSocket实现;HTTP用于Web服务,常借助HttpURLConnection或Apache HttpClient。两者结合,构成网络服务基础。Java有多种高级API和框架(如Netty、Spring Boot)简化开发,助力高效、高并发的网络通信。
|
10天前
|
安全 网络安全 开发工具
对象存储oss使用问题之flutter使用http库进行post请求文件上传返回400如何解决
《对象存储OSS操作报错合集》精选了用户在使用阿里云对象存储服务(OSS)过程中出现的各种常见及疑难报错情况,包括但不限于权限问题、上传下载异常、Bucket配置错误、网络连接问题、跨域资源共享(CORS)设定错误、数据一致性问题以及API调用失败等场景。为用户降低故障排查时间,确保OSS服务的稳定运行与高效利用。
33 1
|
11天前
|
网络协议 安全 API
Android网络和数据交互: 什么是HTTP和HTTPS?在Android中如何进行网络请求?
HTTP和HTTPS是网络数据传输协议,HTTP基于TCP/IP,简单快速,HTTPS则是加密的HTTP,确保数据安全。在Android中,过去常用HttpURLConnection和HttpClient,但HttpClient自Android 6.0起被移除。现在推荐使用支持TLS、流式上传下载、超时配置等特性的HttpsURLConnection进行网络请求。
10 0
|
12天前
|
数据采集 API 数据安全/隐私保护
畅游网络:构建C++网络爬虫的指南
本文介绍如何使用C++和cpprestsdk库构建高效网络爬虫,以抓取知乎热点信息。通过亿牛云爬虫代理服务解决IP限制问题,利用多线程提升数据采集速度。示例代码展示如何配置代理、发送HTTP请求及处理响应,实现多线程抓取。注意替换有效代理服务器参数,并处理异常。
畅游网络:构建C++网络爬虫的指南