2011年6月21日 星期二

[C++]Http Get與Post函式(Curl)

序言

此篇記錄我使用Curl函式庫來達成Http的Get與Post方法。

開發環境

編譯Curl函式庫

  1. 下載curl-7.21.4.zip,解壓縮後可以得到[curl-7.21.4]目錄
  2. 進入[curl-7.21.4]目錄會找到[vc6curl.dsw]專案,以Visual Studio 2008開啟
  3. 建置專案
  4. 建置成功後會在[curl-7.21.4\lib\DLL-Debug]目錄下看到編譯完成的libcurld.dll、libcurld_imp.lib

設定開發專案

  1. 將上一步產生的[libcurld.dll]複製到[C:\WINDOWS\system32]
  2. 於開發用的C++專案設定屬性:展開[組態屬性→C/C++→一般],修改[其他Include目錄],指到[curl-7.21.4]目錄中的include資料夾
  3. 展開[組態屬性→連結器→一般],修改[其他程式庫目錄],指到[curl-7.21.4\lib\DLL-Debug]目錄
  4. 展開[組態屬性→連結器→輸入],修改[其他相依性],,增加[libcurld_imp.lib]


Http連線函式庫

  1. HttpIO.h
    #pragma once
    #include 
    using namespace std;
    namespace commonio {
     class HttpIO
     {
     public:
      /**
      **post方法
      **isRedirect:是否依head redirect
      **param:傳參數,如val1=123&val2=abc
      **timeout:等待回應逾期時間(秒),為不限制
      **/
      static string doPost(string URL,bool isRedirect,string param="",long timeout=0);
      /**
      **get方法
      **isRedirect:是否依head redirect
      **timeout:等待回應逾期時間(秒),為不限制
      **/
      static string doGet(string URL,bool isRedirect,long timeout=0);
     };
    };
  2. HttpIO.cpp
    #include "StdAfx.h"
    #include 
    //#include 
    #include 
    #include "HttpIO.h"
    
    using namespace std;
    using namespace commonio;
    
    
    // This is the writer call back function used by curl
    size_t writer (char *data, size_t size, size_t nmemb, std::string *buffer)
    {
        size_t result = 0;
        if (buffer != NULL)
        {
            buffer->append (data, size * nmemb);
            result = size * nmemb;
        }
        return result;
    }    
    
    
    
    string HttpIO::doPost(string URL,bool isRedirect,string param,long timeout)
    {
        CURL *curl;
        CURLcode cc;
        string bufferdata;
     string error;
     //string user_agent("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
     if ((curl = curl_easy_init()) == NULL)
            exit(1);
     curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
        curl_easy_setopt(curl, CURLOPT_URL, URL.c_str()); // URL used for posting
     //curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent);
     
    
     if(isRedirect) curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //Redirect
     if(timeout>0) curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); //times out after second
        curl_easy_setopt(curl, CURLOPT_POST, 1);//Tell libcurl to use POST
     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, param.c_str());
        curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION,   writer);
        curl_easy_setopt (curl, CURLOPT_WRITEDATA,&bufferdata);
        //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);  //Debug
        //cc=curl_easy_setopt(curl, CURLOPT_HEADER, 1);    //Debug
     cc = curl_easy_perform(curl);
     
        curl_easy_cleanup(curl);
        if(cc == CURLE_OK)
            {
                string data;
                data=bufferdata;
                bufferdata="";
       return data;
            }      
            else
            {
                //cout << "Error: [" << cc << "] - "<< error;
       string data("");
       return data;
            }
    }
    
    string HttpIO::doGet(string URL,bool isRedirect,long timeout)
    {
        CURL *curl;
        CURLcode cc;
    
        string bufferdata;
     string error;
        if ((curl = curl_easy_init()) == NULL)
            exit(1);
     curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
        curl_easy_setopt(curl, CURLOPT_URL, URL.c_str()); // URL used for posting
     if(isRedirect) curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); //Redirect
     if(timeout>0) curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); //times out after second
        curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION,   writer);
        curl_easy_setopt (curl, CURLOPT_WRITEDATA,&bufferdata);
     //cc=curl_easy_setopt(curl, CURLOPT_HEADER, 1);    //Debug
        cc = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
        if(cc == CURLE_OK)
            {
                string data;
                data=bufferdata;
                bufferdata="";
       return data;
            }      
            else
            {
                //cout << "Error: [" << cc << "] - "<< error;
       string data("");
       return data;
            }
    }
  3. 額外函式
    • CommonFunc.h
      #pragma once
      using namespace std;
      namespace commonio {
       class CommonFunc
       {
       public:
        static void str_split(const string& str,
              vector& tokens,
              const string& delimiters = " ");
        static vector> paramToArray(string param);
       };
      };
    • CommonFunc.cpp
      #include "stdafx.h"
      
      #include 
      #include 
      #include "CommonFunc.h"
      using namespace std;
      using namespace commonio;
      void CommonFunc::str_split(const string& str,
                            vector& tokens,
                            const string& delimiters){
          // Skip delimiters at beginning.
          string::size_type lastPos = str.find_first_not_of(delimiters, 0);
          // Find first "non-delimiter".
          string::size_type pos     = str.find_first_of(delimiters, lastPos);
      
          while (string::npos != pos || string::npos != lastPos)
          {
              // Found a token, add it to the vector.
              tokens.push_back(str.substr(lastPos, pos - lastPos));
              // Skip delimiters.  Note the "not_of"
              lastPos = str.find_first_not_of(delimiters, pos);
              // Find next "non-delimiter"
              pos = str.find_first_of(delimiters, lastPos);
          }
      }
      
      
      vector> CommonFunc::paramToArray(string param){
         vector>  arr;
         vector p;
         CommonFunc::str_split(param,p,"&");
         if (param.find("&")>-1) {
          vector p2;
          int j = 0;
          for (unsigned int i = 0; i < p.size(); i++) {
           if (p[i].find_first_of("amp;")==0) {
            p2[j - 1]=p2[j - 1] + "&" + p[i].substr(4);
            j--;
           }
           p2.push_back(p[i]);
           j++;
          }
          p=p2;
         }
      
         for (unsigned int i = 0; i < p.size(); i++) {
          vector item;
          CommonFunc::str_split(p[i],item,"=");
          if (item.size() == 2) {
           arr.push_back(item);
          }
         }
         return arr;
        }

使用範例程式

#include "stdafx.h"
#include 
#include 
#include "HttpIO.h"
using namespace std;
using namespace commonio;

int main(int argc, _TCHAR* argv[])
{
 string data=HttpIO::doGet("http://www.google.com",false);
 cout << '\t' << data << endl;
    return 0;
}

沒有留言:

張貼留言