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

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 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头部。

目录
相关文章
|
1月前
|
域名解析 存储 安全
HTTP【网络】
HTTP协议格式、HTTP的方法 、HTTP的状态码、HTTP常见的Header
233 6
HTTP【网络】
|
3天前
|
网络协议 网络安全 网络虚拟化
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算
本文介绍了十个重要的网络技术术语,包括IP地址、子网掩码、域名系统(DNS)、防火墙、虚拟专用网络(VPN)、路由器、交换机、超文本传输协议(HTTP)、传输控制协议/网际协议(TCP/IP)和云计算。通过这些术语的详细解释,帮助读者更好地理解和应用网络技术,应对数字化时代的挑战和机遇。
22 3
|
14天前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
43 13
|
2月前
|
JavaScript 前端开发 API
网络请求库 – axios库
网络请求库 – axios库
196 60
|
14天前
|
存储 缓存 网络协议
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
|
2月前
|
数据采集 JSON API
🎓Python网络请求新手指南:requests库带你轻松玩转HTTP协议
本文介绍Python网络编程中不可或缺的HTTP协议基础,并以requests库为例,详细讲解如何执行GET与POST请求、处理响应及自定义请求头等操作。通过简洁易懂的代码示例,帮助初学者快速掌握网络爬虫与API开发所需的关键技能。无论是安装配置还是会话管理,requests库均提供了强大而直观的接口,助力读者轻松应对各类网络编程任务。
115 3
|
1月前
|
JSON API 开发者
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
16 0
|
1月前
|
程序员 C++ 开发者
C++入门教程:掌握函数重载、引用与内联函数的概念
通过上述介绍和实例,我们可以看到,函数重载提供了多态性;引用提高了函数调用的效率和便捷性;内联函数则在保证代码清晰的同时,提高了程序的运行效率。掌握这些概念,对于初学者来说是非常重要的,它们是提升C++编程技能的基石。
21 0
|
2月前
|
网络协议 Linux C++
超级好用的C++实用库之网络
超级好用的C++实用库之网络
44 0
|
6天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
29 4