前言

C++中http client库本身就少,好用的就更少了,在了解微软开源的CPP REST SDK库之前,我知道的C++ http client库有libcurl(这个是C语言的),Qt的QNetworkAccessManager,还有VC++ http client,Qt的QNetworkAccessManager库我在开发CZPlayer的时候用来下载过音乐、专辑图片和歌词,不得不说Qt提供的API还是比较好用的,如果不涉及界面开发,难道我们在linux上就只能用libcurl,在windows上就用VC++的http client?答案是否定的,在绝望之际CPP REST SDK出现在我的眼前,CPP REST SDK是微软开源的基于PPL的异步http client,网络层使用的是Boost.Asio,跨平台,并且支持json解析,在使用CPP REST SDK之前要确保你已经安装了boost和openssl,下面是微软官方提供的例子。

微软官方例子

  1. #include <cpprest/http_client.h>
  2. #include <cpprest/filestream.h>
  3. using namespace utility; // Common utilities like string conversions
  4. using namespace web; // Common features like URIs.
  5. using namespace web::http; // Common HTTP functionality
  6. using namespace web::http::client; // HTTP client features
  7. using namespace concurrency::streams; // Asynchronous streams
  8. int main(int argc, char* argv[])
  9. {
  10. auto fileStream = std::make_shared<ostream>();
  11. // Open stream to output file.
  12. pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
  13. {
  14. *fileStream = outFile;
  15. // Create http_client to send the request.
  16. http_client client(U("http://www.bing.com/"));
  17. // Build request URI and start the request.
  18. uri_builder builder(U("/search"));
  19. builder.append_query(U("q"), U("cpprestsdk github"));
  20. return client.request(methods::GET, builder.to_string());
  21. })
  22. // Handle response headers arriving.
  23. .then([=](http_response response)
  24. {
  25. printf("Received response status code:%u\n", response.status_code());
  26. // Write response body into the file.
  27. return response.body().read_to_end(fileStream->streambuf());
  28. })
  29. // Close the file stream.
  30. .then([=](size_t)
  31. {
  32. return fileStream->close();
  33. });
  34. // Wait for all the outstanding I/O to complete and handle any exceptions
  35. try
  36. {
  37. requestTask.wait();
  38. }
  39. catch (const std::exception &e)
  40. {
  41. printf("Error exception:%s\n", e.what());
  42. }
  43. return 0;
  44. }

上面的例子主要内容是访问一个网站并将该内容保存在results.html里面,这里用到了微软自家的PPL并行计算库(还有一个是英特尔的TBB),该例子使用lambda表达式作为异步回调的handler,打开文件流、请求、回应和关闭文件流都是异步的,为了方便起见,我们将该例子改为同步方式。

使用同步方式

  1. auto fileStream = std::make_shared<ostream>();
  2. ostream outFile = fstream::open_ostream(U("results.html")).get();
  3. *fileStream = outFile;
  4. // Create http_client to send the request.
  5. http_client client(U("http://www.bing.com/"));
  6. // Build request URI and start the request.
  7. uri_builder builder(U("/search"));
  8. builder.append_query(U("q"), U("cpprestsdk github"));
  9. http_response response = client.request(methods::GET, builder.to_string()).get();
  10. // Write response body into the file.
  11. response.body().read_to_end(fileStream->streambuf()).get();
  12. fileStream->close().get();

使用同步方式的代码比较清晰,可以看到每一个函数调用后面都会调用get函数,因为CPP REST SDK是基于PPL的,所以在request、read_to_end、close等函数调用后都会返回一个Task对象,而Task里面的get和wait函数是等待任务执行完成。

实战

我之前在看别人博客的时候看到每一篇博客前都有一副图,看起来比较好看,听博主讲他是使用bing的每日一图,后来我也效仿,我在主题之家找到了自己比较喜欢的图片,最开始自己写博客的时候都是直接去主题之家一页一页的找看,然后再下载图片,写了几篇博客之后感觉每次都要去下载图片感觉有点low,所以我决定直接将主题之家的某类型的图片都下载下来,这样选图片就方便多了,下面是我在主题之家抓图的代码。

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <fstream>
  5. #include <memory>
  6. #include <regex>
  7. #include <cpprest/http_client.h>
  8. #include <cpprest/filestream.h>
  9. #include <cpprest/containerstream.h>
  10. // 请求并解析url
  11. bool get_result(const std::string& url, const std::string& pattern, std::vector<std::string>& vec)
  12. {
  13. try
  14. {
  15. web::http::client::http_client client(web::uri(utility::conversions::to_string_t(url)));
  16. web::http::http_response response = client.request(web::http::methods::GET).get();
  17. concurrency::streams::stringstreambuf buffer;
  18. response.body().read_to_end(buffer).get();
  19. std::string& str = buffer.collection();
  20. // 使用C++11提供的正则表达式库
  21. std::regex r(pattern);
  22. for (std::sregex_iterator iter(str.begin(), str.end(), r), end; iter != end; ++iter)
  23. {
  24. std::cout << iter->str() << std::endl;
  25. vec.emplace_back(iter->str());
  26. }
  27. }
  28. catch (std::exception& e)
  29. {
  30. std::cout << "Exception: " << e.what() << std::endl;
  31. return false;
  32. }
  33. return true;
  34. }
  35. // 获取图片
  36. bool get_result(const std::string& url, std::string& picture)
  37. {
  38. try
  39. {
  40. web::http::client::http_client client(web::uri(utility::conversions::to_string_t(url)));
  41. web::http::http_response response = client.request(web::http::methods::GET).get();
  42. concurrency::streams::stringstreambuf buffer;
  43. response.body().read_to_end(buffer).get();
  44. picture = buffer.collection();
  45. }
  46. catch (std::exception& e)
  47. {
  48. std::cout << "Exception: " << e.what() << std::endl;
  49. return false;
  50. }
  51. return true;
  52. }
  53. // 保存图片
  54. bool write_to_file(const std::string& file_path, const std::string& data)
  55. {
  56. try
  57. {
  58. std::ofstream file;
  59. file.open(file_path, std::ios::out | std::ios::binary);
  60. if (!file.good())
  61. {
  62. return false;
  63. }
  64. file.write(data.c_str(), data.size());
  65. file.close();
  66. }
  67. catch (std::exception& e)
  68. {
  69. std::cout << "Exception: " << e.what() << std::endl;
  70. return false;
  71. }
  72. return true;
  73. }
  74. int main()
  75. {
  76. // [1] 请求每一页,将子页面的url保存在sub_url_vec里面
  77. std::vector<std::string> sub_url_vec;
  78. std::string pattern = "/desk/[0-9]+.htm";
  79. for (int i = 1; i <= 32; ++i)
  80. {
  81. // 创意主题
  82. std::string url = "http://www.51ztzj.com/dbizhi/category_27_" + std::to_string(i) + ".htm#content_anchor";
  83. std::cout << "Start get " << i << " page, url: " << url << std::endl;
  84. // 请求并解析url
  85. if (!get_result(url, pattern, sub_url_vec))
  86. {
  87. std::cout << "Get " << i << " page failed" << std::endl;
  88. }
  89. }
  90. // 最终的图片url:http://img.51ztzj.com//upload/image/20130220/2013022014_670x419.jpg
  91. // [2] 将子页面的图片url解析出来放入picture_url_vec
  92. std::vector<std::string> picture_url_vec;
  93. pattern = "http://img.51ztzj.com//upload/image/.+/.+_670x419.jpg";
  94. for (std::size_t i = 0; i < sub_url_vec.size(); ++i)
  95. {
  96. std::string url = "http://www.51ztzj.com" + sub_url_vec[i];
  97. std::cout << "Start get " << i + 1 << " sub page, url: " << url << std::endl;
  98. // 请求并解析url
  99. if (!get_result(url, pattern, picture_url_vec))
  100. {
  101. std::cout << "Get " << i + 1 << " sub page failed" << std::endl;
  102. }
  103. }
  104. // [3] 最后遍历picture_url_vec,然后一个一个的下载图片
  105. for (std::size_t i = 0; i < picture_url_vec.size(); ++i)
  106. {
  107. std::cout << "Start download " << i + 1 << " picture, url: " << picture_url_vec[i] << std::endl;
  108. std::string picture;
  109. // 获取图片
  110. if (!get_result(picture_url_vec[i], picture))
  111. {
  112. std::cout << "Download " << i + 1 << " picture failed" << std::endl;
  113. }
  114. std::string file_path = "./download/" + std::to_string(i) + ".jpg";
  115. // 保存图片
  116. if (!write_to_file(file_path, picture))
  117. {
  118. std::cout << "Write to file failed: " << i + 1 << std::endl;
  119. }
  120. }
  121. return 0;
  122. }

好用的http client库CPP REST SDK的更多相关文章

  1. 【Python】http.client库的用法

    代码: # http.client测试,该库较底层,不常用 import http.client conn=None try: conn=http.client.HTTPSConnection(&qu ...

  2. 一套权威的 MQTT Client 库

    主流的语言都支持,可链接到 github ,亲测golang client 简单好用 http://www.eclipse.org/paho/downloads.php

  3. 开源库Magicodes.WeChat.SDK总体介绍

    目录 1    概要    1 2    主要特点    2 3    架构图    8 3.1    构造器——WeChatSDKBuilder    8 3.2    函数管理器——WeChatF ...

  4. 使用开源库MAGICODES.WECHAT.SDK进行微信公众号支付开发

    概要 博客使用Word发博,发布后,排版会出现很多问题,敬请谅解.可加群获取原始文档. 本篇主要讲解微信支付的开发流程,相关业务基于MAGICODES.WECHAT.SDK实现.通过本篇教程,您可以很 ...

  5. 【Docker】使用Docker Client和Docker Go SDK为容器分配GPU资源

    目录 背景 使用 Docker Client 调用 GPU 依赖安装 安装 Docker 安装 NVIDIA Container Toolkit¶ --gpus 用法 使用 Docker Go SDK ...

  6. 又一个半成品库 weblog rpc client

    我基本上属于半成品专业户,去看我的github就知道. 下午又撸了一个weblog rpc client库,而这又一次证明了一个有技术但没有产品能力的程序员是没有卵用的. 因为当做好了库的雏形,但与具 ...

  7. 更高效地提高redis client多线程操作的并发吞吐设计

    Redis是一个非常高效的基于内存的NOSQL数据库,它提供非常高效的数据读写效能.在实际应用中往往是带宽和CLIENT库读写损耗过高导致无法更好地发挥出Redis更出色的能力.下面结合一些redis ...

  8. 100个Github上Android开源库

    项目名称 项目简介 1. react-native 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开源框架 React Native, ...

  9. GitHub上排名前100的Android开源库介绍(来自github)

    本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍,至于排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果,然后过滤了 ...

随机推荐

  1. videoview 播放视频

    -videoVIew 继承SurfaceView 使用android的VideoView来播放一个视频,步骤是: 1,在xml中创建一个videoView, 2,在java中导入,然后创建一个Medi ...

  2. Transact-SQL小知识

    一.Isnull 函数 Isnull 函数主要作用是将为空的值替换为指定值,如果不为空返回检查类型的返回值,isnull的语法: Isnull (check_expression , replacem ...

  3. redhad linux 7 安装ftp服务

    1. 查看有没有安装 rpm -qa|grep vsftpd 2.安装vsftp yum install vsftpd -y 3. 启动vsftp /sbin/service vsftpd start ...

  4. Xamarin绑定微信SDK 实现分享功能

    从开始做这一块的工作开始,就开始找各种的资料,最后还是老老实实的去看官方文档. 对于Xamarin.Android的绑定属于纯jar的绑定,这个难度较小,添加Bindings Library,将lib ...

  5. Linux Centos 开启防火墙 FirewallD is not running

    转载自:http://www.z4zr.com/page/1006.html CentOS7用firewall命令“替代”了iptables.在这里我们需要区分“iptables服务”和“iptabl ...

  6. 160331、使用@Controller注解为什么要配置<mvc:annotation-driven />

    为了解决静态资源访问的问题,servlet改成了拦截所有请求,即/,并添加了默认的servlet,这时候*.do请求不能被控制器捕捉了,页面错误为404.直到添加了<mvc:annotation ...

  7. /proc/iomem和/proc/ioports对应的fops

    /proc/iomem和/proc/ioports对应的fops static int __init ioresources_init(void) {     struct proc_dir_entr ...

  8. 监控之snmpd 服务

    监控离不开数据采集,经常使用的Mrtg ,Cacti,Zabbix,等等监控软件都是通过snmp 协议进行数据采集的! 1 什么是snmp 协议? 简单网络管理协议(SNMP,Simple Netwo ...

  9. 13.Query for Null or Missing Fields-官方文档摘录

    1 插入数据 db.inventory.insertMany([ { _id: 1, item: null }, { _id: 2 } ]) 2 查询null值 db.inventory.find({ ...

  10. SVN导出Maven项目

    1.从SVN检出项目 -> 作为工作空间中的项目检出 2.转换成Maven project 3.将Maven Project 转化成 Maven app 右击项目-> Properties ...