一、libcurl中的http get使用方法
1. 为什么要使用libcurl
1) 作为http的客户端,可以直接用socket连接服务器,然后对到的数据进行http解析,但要分析协议头,实现代理…这样太麻烦了。
2) libcurl是一个开源的客户端url传输库,支持 FTP,FTPS,TFTP,HTTP,HTTPS,GOPHER,TELNET,DICT,FILE和LDAP,支持 Windows,Unix,Linux等平台,简单易用,且库文件占用空间不到200K
2. get和post方式
客户端在http连接时向服务提交数据的方式分为get和post两种
3.Get方式将所要传输的数据附在网址后面,然后一起送达服务器,它的优点是效率比较高;缺点是安全性差、数据不超过1024个字符、必须是7位的ASCII编码;查询时经常用此方法
4.Post通过Http post处理发送数据,它的优点是安全性较强、支持数据量大、支持字符多;缺点是效率相对低;编辑修改时多使用此方法
5.Get使用实例,其关键点就是设置回调函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "curl/curl.h"
#define HEAD_OUT "/root/project/test/head.out"
#define BODY_OUT "/root/project/test/body.out"
#define RET_EQUAL 0
#define RET_NOT_EQUAL 1
#define RET_NO_UPGRADE_FILE 2
#define RET_FIND_UPGRADE_FILE 3
#define RET_CHECK_OK 4
#define RET_ERROR 5
#define RET_SD_VERSION_ERROR 6
#define RET_OK 7
#define RET_CUR_VERSION_ERROR 8
#define RET_XOR_ERROR 9
#define RET_UPGRADE_OK 10
#define RET_UPGRADE_ERROR 11
#define RET_ERROR_FILE_NAME 12
#define RET_DELAY_CMD_NOT_RUN 13
#define RET_DEALY_CMD_ERROR 14
#define RET_GET_HASH_OK 15
#define RET_GET_HASH_ERROR 16
#define RET_AREADY_CP_VERSION 17
#define RET_NOT_CP_VERSION 18
#define RET_XOR_VERSION 19
#define RET_OPEN_VERSION_LIST_PATH_FAIL 20
#define OPEN_HEAD_FILE_ERROR 21
#define OPEN_BODY_FILE_ERROR 22
#define RET_GET_VERSION_PATH 23
#define RET_NOT_GET_VERSION_PATH 24
#define TIME_OUT 25
#define DOWNLOAD_OK 26
#define LOG fprintf
#define LOG_NOTICE stderr
size_t write_data(void * ptr, size_t size, size_t nmemb, void* stream)
{
int written = fwrite(ptr, size, nmemb, (FILE *)stream);
return written;
}
int detect_version(char * url)
{
CURL * curl_handle;
FILE * headerfile;
FILE * bodyfile;
static const char * headerfilename = HEAD_OUT;
static const char * bodyfilename = BODY_OUT;
// char buffer[STR_LEN] = {'\0'};
int res = 0;
printf("url=%s\n",url);
curl_global_init(CURL_GLOBAL_ALL);
curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
headerfile = fopen(headerfilename, "wb");
if(headerfilename == NULL) {
curl_easy_cleanup(curl_handle);
return OPEN_HEAD_FILE_ERROR;
}
bodyfile = fopen(bodyfilename, "wb");
if(bodyfile == NULL) {
curl_easy_cleanup(curl_handle);
return OPEN_BODY_FILE_ERROR;
}
curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, headerfile);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, bodyfile);
res = curl_easy_perform(curl_handle);
if(res != CURLE_OK)
LOG(LOG_NOTICE, "curl_easy_perform() faild:%s\n",
curl_easy_strerror(res));
fclose(headerfile);
fclose(bodyfile);
curl_easy_cleanup(curl_handle);
return res;
}
int main()
{
detect_version("http://car.9797168.com:823/get_bus_info?mac=00:11:22:33:44:55");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "curl/curl.h"
#define HEAD_OUT "/root/project/test/head.out"
#define BODY_OUT "/root/project/test/body.out"
#define RET_EQUAL 0
#define RET_NOT_EQUAL 1
#define RET_NO_UPGRADE_FILE 2
#define RET_FIND_UPGRADE_FILE 3
#define RET_CHECK_OK 4
#define RET_ERROR 5
#define RET_SD_VERSION_ERROR 6
#define RET_OK 7
#define RET_CUR_VERSION_ERROR 8
#define RET_XOR_ERROR 9
#define RET_UPGRADE_OK 10
#define RET_UPGRADE_ERROR 11
#define RET_ERROR_FILE_NAME 12
#define RET_DELAY_CMD_NOT_RUN 13
#define RET_DEALY_CMD_ERROR 14
#define RET_GET_HASH_OK 15
#define RET_GET_HASH_ERROR 16
#define RET_AREADY_CP_VERSION 17
#define RET_NOT_CP_VERSION 18
#define RET_XOR_VERSION 19
#define RET_OPEN_VERSION_LIST_PATH_FAIL 20
#define OPEN_HEAD_FILE_ERROR 21
#define OPEN_BODY_FILE_ERROR 22
#define RET_GET_VERSION_PATH 23
#define RET_NOT_GET_VERSION_PATH 24
#define TIME_OUT 25
#define DOWNLOAD_OK 26
#define LOG fprintf
#define LOG_NOTICE stderr
size_t write_data(void * ptr, size_t size, size_t nmemb, void* stream)
{
int written = fwrite(ptr, size, nmemb, (FILE *)stream);
return written;
}
int detect_version(char * url)
{
CURL * curl_handle;
FILE * headerfile;
FILE * bodyfile;
static const char * headerfilename = HEAD_OUT;
static const char * bodyfilename = BODY_OUT;
// char buffer[STR_LEN] = {'\0'};
int res = 0;
printf("url=%s\n",url);
curl_global_init(CURL_GLOBAL_ALL);
curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
headerfile = fopen(headerfilename, "wb");
if(headerfilename == NULL) {
curl_easy_cleanup(curl_handle);
return OPEN_HEAD_FILE_ERROR;
}
bodyfile = fopen(bodyfilename, "wb");
if(bodyfile == NULL) {
curl_easy_cleanup(curl_handle);
return OPEN_BODY_FILE_ERROR;
}
curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, headerfile);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, bodyfile);
res = curl_easy_perform(curl_handle);
if(res != CURLE_OK)
LOG(LOG_NOTICE, "curl_easy_perform() faild:%s\n",
curl_easy_strerror(res));
fclose(headerfile);
fclose(bodyfile);
curl_easy_cleanup(curl_handle);
return res;
}
int main()
{
detect_version("http://car.9797168.com:823/get_bus_info?mac=00:11:22:33:44:55");
return 0;
}
6. POST使用实例,POST使用比较复杂但是比较常用
1.一般使用方法,可以解决大多数post数据的问题。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#define POSTURL "http://www.xiami.com/member/login"
#define POSTFIELDS "email=myemail@163.com&password=mypassword&autologin=1&submit=登 录&type="
#define FILENAME "curlposttest.log"
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
int main(int argc, char *argv[]) {
CURL *curl;
CURLcode res;
FILE *fptr;
struct curl_slist *http_header = NULL;
if ((fptr = fopen(FILENAME, "w")) == NULL) {
fprintf(stderr, "fopen file error: %s\n", FILENAME);
exit(1);
}
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, POSTURL);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, POSTFIELDS); //设置post属性,使用&来将表单属性连接在一起
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); //回调函数,可有可无
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fptr); //回调函数写入数据指针
curl_easy_setopt(curl, CURLOPT_POST, 1); //设置libcurl发送的协议
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); //设置版本
curl_easy_setopt(curl, CURLOPT_HEADER, 1); //设置http数据头
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //设置返回的数据量
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/Users/zhu/CProjects/curlposttest.cookie"); //设置cookie,不是必须
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) {
FILE *fptr = (FILE*)userp;
fwrite(buffer, size, nmemb, fptr);
}
2.post高级使用方法,特点简单,但不易于理解,其使用二进制传输的方式,适合于加密数据的传输。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "curl/curl.h"
#include "http_rsa.h"
#define POSTURL "http://10.0.0.13:821/wifibox/"
#define HTTP_UPLOAD_FILD "/root/project/upload/upload.tar.gz"
#define HTTP_POST_TYPE_GPS "gps"
#define HTTP_POST_TYPE_SYS "sys"
#define HTTP_REPORT_TYPE "type"
#define HTTP_REPORT_SIGNATURE "signature"
#define HTTP_REPORT_INDEX "ident"
#define HTTP_REPORT_CONTENT "content"
int report_http_post(char* type, char* index, char* content, char* url)
{
struct curl_httppost *post = NULL;
struct curl_httppost *last = NULL;
CURL *easy_handle = curl_easy_init();
char asr_buff[1024]={0};
int len =0;
// 使用multi-parts form post
curl_easy_setopt(easy_handle, CURLOPT_URL, url);
openssl_rsa_enc(type, strlen(type), asr_buff, &len);
// 文本数据
curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_TYPE, CURLFORM_COPYCONTENTS, type, CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_SIGNATURE, CURLFORM_COPYCONTENTS, asr_buff, CURLFORM_END);
// 文本文件中的数据
//curl_formadd(&post, &last, CURLFORM_COPYNAME, "signature", CURLFORM_FILECONTENT, "/root/project/sys", CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_INDEX, CURLFORM_COPYCONTENTS, index, CURLFORM_END);
if(1) //发送buff
{
curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_CONTENT, CURLFORM_COPYCONTENTS, content, CURLFORM_END);
}
else//发送文件
{
curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_CONTENT, CURLFORM_FILECONTENT, content, CURLFORM_END);
}
curl_easy_setopt(easy_handle, CURLOPT_HTTPPOST, post);
curl_easy_perform(easy_handle);
curl_formfree(post);
curl_easy_cleanup(easy_handle);
curl_global_cleanup();
return 0;
}
#define MSC_INFO "11:22:33:44:55:66"
int main(int argc, char *argv[]) {
report_http_post("buff", MSC_INFO, "{\"date\": \"2013-12-30 12:20:30\"}", POSTURL);
report_http_post("file", MSC_INFO, HTTP_UPLOAD_FILD, POSTURL);
return 0;
}
这个是curl提供的一个高级使用方法,在post/get数据过程中,使用二进制的方式来进行数据交互,解决加密数据传输是乱码的问题。
使用比较简单
1)新建两个发送数据的链表指针
curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_TYPE, CURLFORM_COPYCONTENTS, type, CURLFORM_END);
CURLFORM_COPYNAME:表单属性名称属性
HTTP_REPORT_TYPE:post表单属性名
CURLFORM_COPYCONTENTS:表单值属性,注意,根据所设置的值不一样,来决定表单属性值的格式,可以是buff,可以是文件,图片等。
type:post表单属性值
3)当然,使用curl_formadd方式和一般的curl方法是一样的,需要一般的初始化流程
CURL *easy_handle = curl_easy_init();等
注意,此处可以和一般的curl使用方式兼容,可以设置返回值得回调函数等。