1. 程式人生 > >libcurl庫的http get和http post使用【轉】

libcurl庫的http get和http post使用【轉】

一、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使用例項,其關鍵點就是設定回撥函式

 

[html] view plain copy
  1. <pre code_snippet_id="172026" snippet_file_name="blog_20140126_1_7646331" name="code" class="html"></pre>  
  2. <pre></pre>  
  3. <pre></pre>  
  4. <pre></pre>  

 

[html] view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include "curl/curl.h"  
  5. #define HEAD_OUT "/root/project/test/head.out"  
  6. #define BODY_OUT "/root/project/test/body.out"  
  7. #define RET_EQUAL 0  
  8. #define RET_NOT_EQUAL 1  
  9. #define RET_NO_UPGRADE_FILE 2  
  10. #define RET_FIND_UPGRADE_FILE 3  
  11. #define RET_CHECK_OK 4  
  12. #define RET_ERROR 5  
  13. #define RET_SD_VERSION_ERROR 6  
  14. #define RET_OK 7  
  15. #define RET_CUR_VERSION_ERROR 8  
  16. #define RET_XOR_ERROR 9  
  17. #define RET_UPGRADE_OK 10  
  18. #define RET_UPGRADE_ERROR 11  
  19. #define RET_ERROR_FILE_NAME 12  
  20. #define RET_DELAY_CMD_NOT_RUN 13  
  21. #define RET_DEALY_CMD_ERROR 14  
  22. #define RET_GET_HASH_OK 15  
  23. #define RET_GET_HASH_ERROR 16  
  24. #define RET_AREADY_CP_VERSION 17  
  25. #define RET_NOT_CP_VERSION 18  
  26. #define RET_XOR_VERSION 19  
  27. #define RET_OPEN_VERSION_LIST_PATH_FAIL 20  
  28. #define OPEN_HEAD_FILE_ERROR 21  
  29. #define OPEN_BODY_FILE_ERROR 22  
  30. #define RET_GET_VERSION_PATH 23  
  31. #define RET_NOT_GET_VERSION_PATH 24  
  32. #define TIME_OUT 25  
  33. #define DOWNLOAD_OK 26  
  34. #define LOG fprintf  
  35. #define LOG_NOTICE stderr  
  36. size_t write_data(void * ptr, size_t size, size_t nmemb, void* stream)  
  37. {  
  38. int written = fwrite(ptr, size, nmemb, (FILE *)stream);  
  39. return written;  
  40. }  
  41. int detect_version(char * url)  
  42. {  
  43.   
  44. CURL * curl_handle;  
  45.   
  46. FILE * headerfile;  
  47.   
  48. FILE * bodyfile;  
  49.   
  50. static const char * headerfilename = HEAD_OUT;  
  51.   
  52. static const char * bodyfilename = BODY_OUT;  
  53.   
  54. // char buffer[STR_LEN] = {'\0'};  
  55.   
  56. int res = 0;  
  57.   
  58. printf("url=%s\n",url);  
  59.   
  60. curl_global_init(CURL_GLOBAL_ALL);  
  61.   
  62. curl_handle = curl_easy_init();  
  63.   
  64. curl_easy_setopt(curl_handle, CURLOPT_URL, url);  
  65.   
  66. curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);  
  67.   
  68. curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);  
  69.   
  70. headerfile = fopen(headerfilename, "wb");  
  71.   
  72. if(headerfilename == NULL) {  
  73.   
  74. curl_easy_cleanup(curl_handle);  
  75.   
  76. return OPEN_HEAD_FILE_ERROR;  
  77.   
  78. }  
  79.   
  80. bodyfile = fopen(bodyfilename, "wb");  
  81.   
  82. if(bodyfile == NULL) {  
  83.   
  84. curl_easy_cleanup(curl_handle);  
  85.   
  86. return OPEN_BODY_FILE_ERROR;  
  87.   
  88. }  
  89.   
  90. curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, headerfile);  
  91.   
  92. curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, bodyfile);  
  93.   
  94. res = curl_easy_perform(curl_handle);  
  95.   
  96. if(res != CURLE_OK)  
  97.   
  98. LOG(LOG_NOTICE, "curl_easy_perform() faild:%s\n",  
  99.   
  100. curl_easy_strerror(res));  
  101.   
  102. fclose(headerfile);  
  103.   
  104. fclose(bodyfile);  
  105.   
  106. curl_easy_cleanup(curl_handle);  
  107.   
  108. return res;  
  109.   
  110. }  
  111. int main()  
  112. {  
  113.     detect_version("http://car.9797168.com:823/get_bus_info?mac=00:11:22:33:44:55");  
  114.     return 0;  
  115. }  



6. POST使用例項,POST使用比較複雜但是比較常用

1.一般使用方法,可以解決大多數post資料的問題。

 

[html] view plain copy
  1. #include <stdio.h>     
  2. #include <stdlib.h>     
  3. #include <string.h>     
  4. #include <curl/curl.h>     
  5.     
  6. #define POSTURL "http://www.xiami.com/member/login"     
  7. #define POSTFIELDS "email=[email protected]&password=mypassword&autologin=1&submit=登 錄&type="     
  8. #define FILENAME "curlposttest.log"     
  9.     
  10. size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);     
  11.     
  12. int main(int argc, char *argv[]) {     
  13.     CURL *curl;     
  14.     CURLcode res;     
  15.     FILE *fptr;     
  16.     struct curl_slist *http_header = NULL;     
  17.     
  18.     if ((fptr = fopen(FILENAME, "w")) == NULL) {     
  19.         fprintf(stderr, "fopen file error: %s\n", FILENAME);     
  20.         exit(1);     
  21.     }     
  22.     
  23.     curl = curl_easy_init();     
  24.     curl_easy_setopt(curl, CURLOPT_URL, POSTURL);     
  25.     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, POSTFIELDS);   //設定post屬性,使用&來將表單屬性連線在一起  
  26.     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);   //回撥函式,可有可無  
  27.     curl_easy_setopt(curl, CURLOPT_WRITEDATA, fptr);           //回撥函式寫入資料指標  
  28.     curl_easy_setopt(curl, CURLOPT_POST, 1);                 //設定libcurl傳送的協議  
  29.     curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);              //設定版本  
  30.     curl_easy_setopt(curl, CURLOPT_HEADER, 1);               //設定http資料頭  
  31.     curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);       //設定返回的資料量  
  32.     curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/Users/zhu/CProjects/curlposttest.cookie");   //設定cookie,不是必須  
  33.     res = curl_easy_perform(curl);     
  34.     curl_easy_cleanup(curl);     
  35. }     
  36.     
  37. size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) {     
  38.     FILE *fptr = (FILE*)userp;     
  39.     fwrite(buffer, size, nmemb, fptr);     
  40. }    



2.post高階使用方法,特點簡單,但不易於理解,其使用二進位制傳輸的方式,適合於加密資料的傳輸。

 

[html] view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <string.h>  
  4. #include "curl/curl.h"    
  5. #include "http_rsa.h"  
  6.   
  7. #define POSTURL "http://10.0.0.13:821/wifibox/"  
  8.    
  9. #define HTTP_UPLOAD_FILD "/root/project/upload/upload.tar.gz"  
  10. #define HTTP_POST_TYPE_GPS "gps"  
  11. #define HTTP_POST_TYPE_SYS "sys"  
  12. #define HTTP_REPORT_TYPE "type"  
  13. #define HTTP_REPORT_SIGNATURE "signature"  
  14. #define HTTP_REPORT_INDEX "ident"  
  15. #define HTTP_REPORT_CONTENT "content"  
  16. int report_http_post(char* type, char* index, char* content, char* url)  
  17. {  
  18.   
  19.  struct curl_httppost *post = NULL;  
  20.   
  21.  struct curl_httppost *last = NULL;  
  22.   
  23.  CURL *easy_handle = curl_easy_init();  
  24.   
  25.  char asr_buff[1024]={0};  
  26.   
  27.  int len =0;  
  28.   
  29.    
  30.   
  31.  // 使用multi-parts form post  
  32.   
  33.  curl_easy_setopt(easy_handle, CURLOPT_URL, url);  
  34.   
  35.  openssl_rsa_enc(type, strlen(type), asr_buff, &len);  
  36.   
  37.  // 文字資料  
  38.   
  39.  curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_TYPE, CURLFORM_COPYCONTENTS, type, CURLFORM_END);  
  40.   
  41.  curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_SIGNATURE, CURLFORM_COPYCONTENTS, asr_buff, CURLFORM_END);  
  42.   
  43.  // 文字檔案中的資料  
  44.   
  45.  //curl_formadd(&post, &last, CURLFORM_COPYNAME, "signature", CURLFORM_FILECONTENT, "/root/project/sys", CURLFORM_END);  
  46.   
  47.  curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_INDEX, CURLFORM_COPYCONTENTS, index, CURLFORM_END);  
  48.   
  49.  if(1) //傳送buff  
  50.   
  51.  {  
  52.   
  53.   curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_CONTENT, CURLFORM_COPYCONTENTS, content, CURLFORM_END);  
  54.   
  55.  }  
  56.   
  57.  else//傳送檔案  
  58.   
  59.  {  
  60.   
  61.   curl_formadd(&post, &last, CURLFORM_COPYNAME, HTTP_REPORT_CONTENT, CURLFORM_FILECONTENT, content, CURLFORM_END);  
  62.   
  63.  }  
  64.   
  65.  curl_easy_setopt(easy_handle, CURLOPT_HTTPPOST, post);  
  66.   
  67.  curl_easy_perform(easy_handle);  
  68.   
  69.  curl_formfree(post);  
  70.   
  71.  curl_easy_cleanup(easy_handle);  
  72.   
  73.  curl_global_cleanup();  
  74.   
  75.  return 0;  
  76.   
  77. }  
  78. #define MSC_INFO "11:22:33:44:55:66"  
  79. int main(int argc, char *argv[]) {  
  80.   
  81.  report_http_post("buff", MSC_INFO, "{\"date\": \"2013-12-30 12:20:30\"}", POSTURL);  
  82.   
  83.  report_http_post("file", MSC_INFO, HTTP_UPLOAD_FILD, POSTURL);  
  84.   
  85.  return 0;  
  86.   
  87. }  


 

這個是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使用方式相容,可以設定返回值得回撥函式等。