libcurl庫的http get和http post使用【轉】
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使用例項,其關鍵點就是設定回撥函式
[html] view plain copy
- <pre code_snippet_id="172026" snippet_file_name="blog_20140126_1_7646331" name="code" class="html"></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
[html] view plain copy
- #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資料的問題。
[html] view plain copy
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <curl/curl.h>
- #define POSTURL "http://www.xiami.com/member/login"
- #define POSTFIELDS "email=[email protected]&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高階使用方法,特點簡單,但不易於理解,其使用二進位制傳輸的方式,適合於加密資料的傳輸。
[html] view plain copy
- #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)新建兩個傳送資料的連結串列指標
struct curl_httppost *post = NULL; struct curl_httppost *last = NULL;
2)使用curl_formadd函式將連結串列指標新增進發送佇列中。
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使用方式相容,可以設定返回值得回撥函式等。