- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
LibCurl是一个开源的免费的多协议数据传输开源库,该框架具备跨平台性,开源免费,并提供了包括 HTTP 、 FTP 、 SMTP 、 POP3 等协议的功能,使用 libcurl 可以方便地进行网络数据传输操作,如发送 HTTP 请求、下载文件、发送电子邮件等。它被广泛应用于各种网络应用开发中,特别是涉及到数据传输的场景.
首先读者需要自行下载该库,如下笔者选择下载 curl-8.0.1.zip 这个源代码版本,读者可找到如下页面,并点击对应版本完成下载,当下载好以后读者可自行将其解压缩到任意目录下.
当读者解压缩后,可打开 VS2013 开发人员命令提示 并切换带该目录中的 curl-8.0.1\winbuild 目录,通过执行如下两条命令即可分别实现编译静态库或动态库,我们以静态库编译为主,执行如下命令读者可自行等待一段时间.
这个库在编译通过后会自动生成文件到 builds\libcurl-vc13-x86-release-static-ipv6-sspi-schannel 目录内,读者可自行打开该目录,即可看到该目录内的头文件以及库目录文件,如下图所示; 。
读者可自行配置这个静态库,通常只需要配置 include 和 lib 文件即可,该库的使用很简单,首先我们需要调用 curl_easy_init() 函数对 CURL 对象进行初始化,接着通过调用 curl_easy_setopt() 并传入一个访问 URL 链接,当访问成功后则可调用 curl_easy_perform() 函数得到访问结果,这就是该库基本使用方法,如下代码.
#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include "curl/curl.h"
#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")
using namespace std;
int main(int argc, char *argv[])
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, "https://www.lyshark.com");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
std::cout << "返回状态: " << res << std::endl;
system("pause");
return 0;
}
运行上述代码,读者可看到网站 www.lyshark.com 的源代码,如下图所示; 。
上述代码中的 curl_easy_setopt() 函数第二个参数可以使用多种类型的变量定义,我们可以通过传入不同的常量来定义请求头中的参数,例如当我们需要修改协议头时,可以使用 CURLOPT_HTTPHEADER 常量,并在其后第三个参数中传入该常量所对应的结构即可,这个结构体定义有许多类型,具体如下下表所示; 。
常量名称 | 描述 |
---|---|
CURLINFO_EFFECTIVE_URL | 最后一个有效的URL地址 |
CURLINFO_HTTP_CODE | 最后一个收到的HTTP代码 |
CURLINFO_FILETIME | 远程获取文档的时间,如果无法获取,则返回值为-1 |
CURLINFO_TOTAL_TIME | 最后一次传输所消耗的时间 |
CURLINFO_NAMELOOKUP_TIME | 名称解析所消耗的时间 |
CURLINFO_CONNECT_TIME | 建立连接所消耗的时间 |
CURLINFO_PRETRANSFER_TIME | 从建立连接到准备传输所使用的时间 |
CURLINFO_STARTTRANSFER_TIME | 从建立连接到传输开始所使用的时间 |
CURLINFO_REDIRECT_TIME | 在事务传输开始前重定向所使用的时间 |
CURLINFO_SIZE_UPLOAD | 以字节为单位返回上传数据量的总值 |
CURLINFO_SIZE_DOWNLOAD | 以字节为单位返回下载数据量的总值 |
CURLINFO_SPEED_DOWNLOAD | 平均下载速度 |
CURLINFO_SPEED_UPLOAD | 平均上传速度 |
CURLINFO_HEADER_SIZE | header部分的大小 |
CURLINFO_HEADER_OUT | 发送请求的字符串 |
CURLINFO_REQUEST_SIZE | 在HTTP请求中有问题的请求的大小 |
CURLINFO_SSL_VERIFYRESULT | 通过设置CURLOPT_SSL_VERIFYPEER返回的SSL证书验证请求的结果 |
CURLINFO_CONTENT_LENGTH_DOWNLOAD | 从Content-Length: field中读取的下载内容长度 |
CURLINFO_CONTENT_LENGTH_UPLOAD | 上传内容大小的说明 |
CURLINFO_CONTENT_TYPE | 下载内容的Content-Type:值,NULL表示服务器没有发送有效的Content-Type:header |
如下案例是一个简单的 GET 请求封装,通过调用 GetStatus() 函数实现对特定页面发起请求的功能,其中 curl_slist_append() 用于增加新的请求头数据,在调用 curl_easy_setopt() 函数时,分别传入了 CURLOPT_HTTPHEADER 设置请求头, CURLOPT_WRITEFUNCTION 设置回调, CURLINFO_PRIMARY_IP 获取目标 IP 地址, CURLINFO_RESPONSE_CODE 获取目标返回代码,此处的 write_data() 函数直接返回0则表示屏蔽所有的页面输出内容.
#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include "curl/curl.h"
#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")
using namespace std;
// 设置CURLOPT_WRITEFUNCTION回调函数,返回为空屏蔽输出
static size_t write_data(char *d, size_t n, size_t l, void *p)
{
return 0;
}
// 获取网站返回值
void GetStatus(char *UrlPage)
{
CURLcode return_code;
// 初始化模块
return_code = curl_global_init(CURL_GLOBAL_WIN32);
if (CURLE_OK != return_code)
{
return;
}
// 初始化填充请求头
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0)");
headers = curl_slist_append(headers, "Referer: https://www.lyshark.com");
// 初始化请求库
CURL *easy_handle = curl_easy_init();
if (NULL != easy_handle)
{
// CURLOPT_HTTPHEADER 自定义设置请求头
curl_easy_setopt(easy_handle, CURLOPT_HTTPHEADER, headers);
// CURLOPT_URL 自定义请求的网站
curl_easy_setopt(easy_handle, CURLOPT_URL, UrlPage);
// CURLOPT_WRITEFUNCTION 设置回调函数,屏蔽输出
curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data);
// 执行CURL访问网站
return_code = curl_easy_perform(easy_handle);
char *ipAddress = { 0 };
// CURLINFO_PRIMARY_IP 获取目标IP信息
return_code = curl_easy_getinfo(easy_handle, CURLINFO_PRIMARY_IP, &ipAddress);
if ((CURLE_OK == return_code) && ipAddress)
{
std::cout << "目标IP: " << ipAddress << std::endl;
}
long retcode = 0;
// CURLINFO_RESPONSE_CODE 获取目标返回状态
return_code = curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &retcode);
if ((CURLE_OK == return_code) && retcode)
{
std::cout << "返回状态码: " << retcode << std::endl;
}
}
curl_easy_cleanup(easy_handle);
curl_global_cleanup();
}
int main(int argc, char *argv[])
{
GetStatus("https://www.lyshark.com");
system("pause");
return 0;
}
运行上述代码,则可以获取到 www.lyshark.com 目标主机的IP地址以及页面返回状态,如下图所示; 。
当然该库同样支持 POST 请求方式,在使用 POST 请求时我们可以通过 CURLOPT_COOKIEFILE 参数指定 Cookie 参数,通过 CURLOPT_POSTFIELDS 指定 POST 的数据集,而如果需要使用代理模式则可以通过 CURLOPT_PROXY 方式来指定代理地址, 。
#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include "curl/curl.h"
#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")
using namespace std;
bool SendPost(char *Url, char *Cookie, char *PostVal)
{
CURL *curl;
CURLcode res;
// 初始化库
curl = curl_easy_init();
if (curl)
{
// 设置请求头
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0)");
headers = curl_slist_append(headers, "Referer: https://www.lyshark.com");
// 设置请求头
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// 指定URL
curl_easy_setopt(curl, CURLOPT_URL, Url);
// 指定cookie参数
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, Cookie);
// 指定post内容
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, PostVal);
// 是否代理
// curl_easy_setopt(curl, CURLOPT_PROXY, "10.99.60.201:8080");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return true;
}
int main(int argc, char *argv[])
{
// 传入网址 cookie 以及post参数
SendPost("https://www.lyshark.com/post.php", "1e12sde342r2", "&logintype=uid&u=xieyan&psw=xxx86");
system("pause");
return 0;
}
该函数的调用需要有一个POST结构才可测试,此处由于我并没有指定接口所有返回了页面错误信息,如下图所示; 。
接着继续实现下载页面到本地的功能,该功能实现的原理是利用 write_data 回调函数,当页面数据被读入到内存时回调函数会被触发,在该回调函数的内部通过调用 fwrite 函数将 ptr 指针中的数据保存本地,实现这段代码如下所示; 。
#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include "curl/curl.h"
#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")
using namespace std;
FILE *fp;
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
int written = fwrite(ptr, size, nmemb, (FILE *)fp);
return written;
}
BOOL GetUrl(char *URL, char *FileName)
{
CURL *curl;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, URL);
// 在屏幕打印请求连接过程和返回http数据
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// 查找次数,防止查找太深
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1);
// 设置连接超时
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
// 接收数据时超时设置
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
if ((fp = fopen(FileName, "w")) == NULL)
{
curl_easy_cleanup(curl);
return FALSE;
}
// CURLOPT_WRITEFUNCTION 将后继的动作交给write_data函数处理
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return TRUE;
}
int main(int argc, char *argv[])
{
// 下载网页到本地
GetUrl("https://www.lyshark.com", "./lyshark.html");
system("pause");
return 0;
}
当读者运行上述程序后,即可将 www.lyshark.com 网站页面源码,下载到本地当前目录下 lyshark.html ,输出效果如下图所示; 。
为了能解析参数,我们还是需要将页面源代码读入到内存中,要实现这个需求并不难,首先我们定义一个 std::string 容器,然后当有新数据产生时触发 WriteCallback 在该函数内,我们直接将数据拷贝到一个内存指针中,也就是存储到 read_buffer 内,并将该缓冲区返回给调用者即可,如下则是完整源代码.
#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include <string>
#include "curl/curl.h"
#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")
using namespace std;
// 存储回调函数
size_t WriteCallback(char *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
// 获取数据并放入string中.
std::string GetUrlPageOfString(std::string url)
{
std::string read_buffer;
CURL *curl;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl)
{
// 忽略证书检查
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
// 重定向
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
// URL路径
curl_easy_setopt(curl, CURLOPT_URL, url);
// 查找次数,防止查找太深
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 1);
// 连接超时
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
// 接收数据时超时设置
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
// 写入回调函数
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &read_buffer);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return read_buffer;
}
return "None";
}
int main(int argc, char *argv[])
{
std::string urls = GetUrlPageOfString("https://www.lyshark.com");
std::cout << "接收长度: " << urls.length() << " bytes" << std::endl;
system("pause");
return 0;
}
如下图所示,则是运行后输出内存数据长度,当然我们也可以直接输出 urls 中的数据,也就是网页的源代码; 。
本文作者: 王瑞 本文链接: https://www.lyshark.com/post/6aa9753b.html 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处! 。
最后此篇关于C++LibCurl库的使用方法的文章就讲到这里了,如果你想了解更多关于C++LibCurl库的使用方法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!