c++ curl使用ip4_C/C++中libcurl的使用-Http GET方法使用详解

Curl是一个命令行工具,用于以特定的URL语法进行数据传输。libcrul是一个用于完成此项工作的curl库。借助libcurl,使用C/C++可以完成文件的下载,HTTP get,post等很多工作。本文介绍使用libcurl的C API完成HTTP中的GET操作。

下面的代码用于使用HTTP get协议,发送请求到一个网址,当请求被正确响应后,将响应的结果页面内容写成一个文件,保存在本地磁盘。

//getDataByCurl.cpp

#include

#include

#include

#include ;

#include

#include

#include

using namespace std;

struct MemoryStruct

{

char *memory;

size_t size;

MemoryStruct()

{

memory = (char *)malloc(1);

size = 0;

}

~MemoryStruct()

{

free(memory);

memory = NULL;

size = 0;

}

};

size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)

{

size_t realsize = size * nmemb;

struct MemoryStruct *mem = (struct MemoryStruct *)data;

mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);

if (mem->memory)

{

memcpy(&(mem->memory[mem->size]), ptr, realsize);

mem->size += realsize;

mem->memory[mem->size] = 0;

}

return realsize;

}

int main()

{

CURLcode res = curl_global_init(CURL_GLOBAL_ALL);

if(CURLE_OK != res)

{

cout<

return 1;

}

CURL *pCurl = NULL;

pCurl = curl_easy_init();

if( NULL == pCurl)

{

cout<

return -1;

}

string url = "http://xx.xx.xx.xx:50070/dfshealth.html"; //待请求的页面

string filename = "dfshealth.html"; //正确响应后,请请求转写成本地文件的文件名即路径,此处表示当前目录下

curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 3L);//请求超时时长

curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, 10L); //连接超时时长

curl_easy_setopt(pCurl, CURLOPT_FOLLOWLOCATION, 1L);//允许重定向

curl_easy_setopt(pCurl, CURLOPT_HEADER, 0L);  //若启用,会将头文件的信息作为数据流输出

curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);  //得到请求结果后的回调函数

MemoryStruct oDataChunk;  //请求结果的保存格式

curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &oDataChunk);

curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 1L); //关闭中断信号响应

curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 1L); //启用时会汇报所有的信息

curl_easy_setopt(pCurl, CURLOPT_URL, url.c_str() ); //需要获取的URL地址

curl_slist *pList = NULL;

pList = curl_slist_append(pList,"Accept-Encoding:gzip, deflate, sdch");

pList = curl_slist_append(pList,"Accept-Language:zh-CN,zh;q=0.8");

pList = curl_slist_append(pList,"Connection:keep-alive");

curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pList);

res = curl_easy_perform(pCurl);  //执行请求

long res_code=0;

res=curl_easy_getinfo(pCurl, CURLINFO_RESPONSE_CODE, &res_code);

//正确响应后,请请求转写成本地文件的文件

if(( res == CURLE_OK ) && (res_code == 200 || res_code == 201))

{

FILE* fTmpMem = (FILE*)oDataChunk.memory;

if (!fTmpMem) {

}

FILE *fp=fopen(filename.c_str(),"wb");

if(!fp)

{

cout<

return -1;

}

fwrite(fTmpMem, 1, oDataChunk.size, fp);

fclose(fp);

return true;

}

curl_slist_free_all(pList);

curl_easy_cleanup(pCurl);

curl_global_cleanup();

return 0;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

编译,执行:

# g++ -g getDataByCurl.cpp -o run -lcurl

# ./run

* About to connect() to xx.xx.xx.xx port 50070 (#0)

*   Trying xx.xx.xx.xx... * connected

* Connected to xx.xx.xx.xx (xx.xx.xx.xx) port 50070 (#0)

> GET /dfshealth.html HTTP/1.1

Host: xx.xx.xx.xx:50070

Accept: */*

Accept-Encoding:gzip, deflate, sdch

Accept-Language:zh-CN,zh;q=0.8

Connection:keep-alive

< HTTP/1.1 200 OK

< Cache-Control: no-cache

< Expires: Tue, 17 Oct 2017 02:49:59 GMT

< Date: Tue, 17 Oct 2017 02:49:59 GMT

< Pragma: no-cache

< Expires: Tue, 17 Oct 2017 02:49:59 GMT

< Date: Tue, 17 Oct 2017 02:49:59 GMT

< Pragma: no-cache

< Content-Type: text/html; charset=utf-8

< Accept-Ranges: bytes

< Content-Length: 13320

< Last-Modified: Thu, 18 Aug 2016 01:49:57 GMT

< Server: Jetty(6.1.26)

<

* Connection #0 to host xx.xx.xx.xx left intact

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

程序执行完后,会在当前目录下生成名为dfshealth.html的文件,该文件内容即为配置的url地址的页面。

在上述代码中,程序试图获取整个网页的结果,如果客户端是多线程的,务必将CURLOPT_NOSIGNAL置为1。结构体MemoryStruct是自定义的数据结构,用于保存CURL执行的结果,CURLOPT_WRITEDATA将该对象传递给回调函数,在回调函数WriteMemoryCallback中,将返回结果分配存储空间,并拷贝返回内存到MemoryStruct对象中。通过curl_easy_getinfo获取curl执行结果的会话信息,将判断执行成功时,客户端将MemoryStruct对象的内容写到指定文件中。

相关接口及参数说明:

CURL_EXTERN CURLcode curl_global_init(long flags);

1

该函数用于操作前的全局初始化,它是非线程安全的,它应该在所有其他libcurl函数调用之前被调用,而且只能被调用一次。如果用户没有调用该函数,那么在后续调用curl_easy_init()进行初始化时,会自动调用curl_global_init(CURL_GLOBAL_DEFAULT),以确保初始化了”global SSL stuff”,参见lib/easy.c源码。

参数:

CURL_GLOBAL_ALL   初始化除CURL_GLOBAL_ACK_EINTR外的所有系统。

CURL_GLOBAL_SSL   初始化SSL

CURL_GLOBAL_WIN32   初始化Win32 socket libraries.

CURL_GLOBAL_NOTHING   不初始化任何系统

CURL_GLOBAL_DEFAULT   等同于CURL_GLOBAL_ALL

CURL_GLOBAL_ACK_EINTR   设置了这个标签后,当curl在连接或等待数据请求时,curl将接收EINTR条件,否则,curl会一直等待。

返回值:

正常通过时返回0,非零值表示出现错误。

CURL_EXTERN void curl_global_cleanup(void);

1

该函数用于进行全局的清理工作,对于使用libcurl的每一个应用,应该只被调用一次。

CURL_EXTERN CURL *curl_easy_init(void);

1

外部接口,用于创建,分配并返回一个初始化的CURL句柄,作为其他curl_easy函数的作用对象。

CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT, long timeout);

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT_MS, long timeout);

1

2

3

外部接口,用于配置CURL对象的选项参数。上述代码中涉及的一些参数选项:

CURLOPT_TIMEOUT:一个完整的请求的超时时长,前者时间单位为秒,后者为毫秒。如果CURLOPT_TIMEOUT和CURLOPT_TIMEOUT_MS都设置了,那么后面的设置将会覆盖前面的设置。

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT, long timeout);

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT_MS, long timeout);

1

2

CURLOPT_CONNECTTIMEOUT:配置在建立请求的链接阶段的超时时长限制,关于时长的参数与上面的TIMEOUT类似。

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FOLLOWLOCATION, long enable);

CURLOPT_FOLLOWLOCATION:使用enable参数控制是否允许URL地址的重定向,关于地址的重定向请参见其他资料。

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADER, long onoff);

CURLOPT_HEADER:当onoff被设置为1时,即告诉libcurl在输出请求体时包含头部信息。

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEFUNCTION, write_callback);

CURLOPT_WRITEFUNCTION:传递调用完成时的回调函数,回调函数的原型为:

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEDATA, void *pointer);

CURLOPT_WRITEDATA:一个自定义的指针pointer,用于传递给上面的write_callback

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOSIGNAL, long onoff);

CURLOPT_NOSIGNAL:如果是多线程,请将该参数置为1。这个选项用于unix环境下的多线程应用仍然可以使用各种timeout选项,而不会引发信号中断致使程序退出。

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_VERBOSE, long onoff);

CURLOPT_VERBOSE:如果将onoff置为1,那么将使得调用过程中输出更多的关于调用操作的详细信息。

CURLcode curl_easy_setopt(CURL *handle, CURLOPT_URL, char *URL);

CURLOPT_URL:请求的url地址

curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, pList);

CURLOPT_HTTPHEADER:设置HTTP请求的头信息

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

更多其他参数详见源码”docs/libcurl/opts”

CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,const char *);

向curl_slist链表中追加参数,curl_slist_append()函数是很有用的,因为如果你什么都不写,CUrl会传输一个类似"Get /你的网页 accept:*/*"之类的简单协议,在某些验证较为严格的服务器,这样的Http链接协议字会被丢弃的。 curl_slist_append()这个API可以让你伪装成一个标准的网页浏览器的请求。关于相关的请求参数,可以通过浏览器的开发者中工具中预先查看。

CURL_EXTERN void curl_slist_free_all(struct curl_slist *);

用于释放之前curl_slist中数据

CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);

外部接口,用于执行CURL对象,是一个阻塞类型的操作

CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);

从curl执行结果中获取内部信息。该函数的第三个参数必须是一个指向long,char或者double类型的指针,当函数执行结果返回CURLE_OK时,该指针的结果将会根据实际情况被填充响应的结果。

CURL_EXTERN void curl_easy_cleanup(CURL *curl);

调用该函数来结束一个curl easy会话。关闭一个由curl_easy_init()生成的handle

---------------------

作者:cjf_wei

来源:CSDN

原文:https://blog.csdn.net/cjf_wei/article/details/79118415

版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 C++cURL 库读取 multipart/x-mixed-replace 格式的数据流,可以按照以下步骤进行: 1. 初始化 cURL 库,并设置 HTTP GET 请求的 URL。 ```c++ // 初始化 cURLcurl_global_init(CURL_GLOBAL_ALL); // 创建一个 cURL 句柄 CURL* curl = curl_easy_init(); // 设置 HTTP GET 请求的 URL curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/stream"); ``` 2. 设置 cURL 句柄的选项,以支持读取 multipart/x-mixed-replace 数据流。 ```c++ // 设置 HTTP GET 请求 curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); // 设置回调函数,处理接收到的数据流 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); // 设置回调函数的参数,以传递用户自定义数据 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); ``` 其,WriteCallback 是一个用户自定义的回调函数,用于处理接收到的数据流。可以定义为类的静态成员函数,也可以定义为全局函数。其函数原型如下: ```c++ size_t WriteCallback(char* ptr, size_t size, size_t nmemb, void* userdata) ``` 在该回调函数,需要将接收到的数据流分解为多个 MIME 部分,并对每个部分进行处理。 3. 执行 HTTP GET 请求,并等待服务器响应。 ```c++ // 执行 HTTP GET 请求,并等待服务器响应 CURLcode res = curl_easy_perform(curl); // 检查 HTTP 请求是否成功 if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } ``` 4. 清理 cURL 句柄和 cURL 库。 ```c++ // 清理 cURL 句柄 curl_easy_cleanup(curl); // 清理 cURLcurl_global_cleanup(); ``` 下面是一个简单的示例代码,用于读取 multipart/x-mixed-replace 格式的数据流并输出到控制台: ```c++ #include <iostream> #include <curl/curl.h> // 回调函数,用于处理接收到的数据流 static size_t WriteCallback(char* ptr, size_t size, size_t nmemb, void* userdata) { std::cout << "Received data: " << std::string(ptr, size * nmemb) << std::endl; // 返回接收到的数据长度 return size * nmemb; } int main() { // 初始化 cURLcurl_global_init(CURL_GLOBAL_ALL); // 创建一个 cURL 句柄 CURL* curl = curl_easy_init(); // 设置 HTTP GET 请求的 URL curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/stream"); // 设置 HTTP GET 请求 curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); // 设置回调函数,处理接收到的数据流 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); // 执行 HTTP GET 请求,并等待服务器响应 CURLcode res = curl_easy_perform(curl); // 检查 HTTP 请求是否成功 if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } // 清理 cURL 句柄 curl_easy_cleanup(curl); // 清理 cURLcurl_global_cleanup(); return 0; } ``` 需要注意的是,这只是一个简单的示例代码,实际应用还需要根据具体情况进行修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值