Linux下使用curl库做HTTP GET、POST请求
linux下用c语言,可以使用curl库来实现相关http get、post之类的操作,看例子:
log.h
#ifndef _LOG_GLOBAL_H_
#define _LOG_GLOBAL_H_
#define LOG_DEBUG       1
#define LOG_GLOBAL_PATH “/media/sdcard/license_client/”
#define LOG_GLOBAL_FILE “license_client.log”
#define LOG_GLOBAL_MAX_LINE 100000
extern int InitLog();
extern int UninitLog();
extern void Log(const char *p_fmt, …);
extern void LogHex(char *pData, size_t size);
#endif /*_LOG_GLOBAL_H_*/
log.c
每10万行切换一个log文件名。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <malloc.h>
#include <stdarg.h>
#include <errno.h>
#include<sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#include “log.h”
FILE *logGlobalFd = NULL;
unsigned int logGlobalLineNum = 0;
pthread_mutex_t logGlobalMutex;
int InitLog()
{
charlog[256];
#ifdef LOG_DEBUG
if(logGlobalFd){
return1; //already init.
}
mkdir(LOG_GLOBAL_PATH, 0755);
snprintf(log, sizeof(log), “%s/%s”, LOG_GLOBAL_PATH, LOG_GLOBAL_FILE);
logGlobalFd = fopen((char*)log, “a”);
if (!logGlobalFd){
printf(“%s=>%s(): failed to open log file (errno=%s)\n”, __FILE__, __FUNCTION__, strerror(errno));
return-1;
}
printf(“%s=>%s(): creat log file %s sucessfull!\n”, __FILE__, __FUNCTION__, log);
// init mutex
if (pthread_mutex_init(&logGlobalMutex, NULL) !=0){
fclose(logGlobalFd);
printf(“%s=>%s(): init mutex error!\n”, __FILE__, __FUNCTION__);
return-1;
}
#endif //LOG_DEBUG
return1;
}
int UninitLog()
{
#ifdef LOG_DEBUG
if(logGlobalFd){
fclose(logGlobalFd);
pthread_mutex_destroy(&logGlobalMutex);
}
#endif //LOG_DEBUG
return1;
}
static int LogNewLogFile()
{
chartmp[256];
chartmp2[256];
chardate[128];
time_t now;
struct tm ptm;
if (logGlobalFd)
{
fclose(logGlobalFd);
time(&now);
localtime_r(&now,&ptm);
strftime((char*)date, 128, “_%F_%T”, &ptm);
snprintf(tmp, sizeof(tmp), “%s/%s”, LOG_GLOBAL_PATH, LOG_GLOBAL_FILE);
snprintf(tmp2, sizeof(tmp2), “%s_%s.log”, tmp, date);
remove(tmp2);
rename(tmp, tmp2);
logGlobalFd = fopen((char*)tmp, “a”);
}
return1;
}
void Log(const char *p_fmt, …)
{
chardate[256];
time_t now;
struct tm ptm;
va_list ap;
#ifdef LOG_DEBUG
if (!logGlobalFd){
return;
}
pthread_mutex_lock(&logGlobalMutex);
time(&now); // Gets the system time
if (localtime_r(&now, &ptm))
{
strftime(date, sizeof (date), “%F %T”, &ptm);
fprintf(logGlobalFd, “%s “, date);
va_start(ap, p_fmt);
vfprintf(logGlobalFd, p_fmt, ap);
va_end(ap);
fflush(logGlobalFd);
logGlobalLineNum++;
if (logGlobalLineNum > LOG_GLOBAL_MAX_LINE){
LogNewLogFile();
logGlobalLineNum = 0;
}
}
pthread_mutex_unlock(&logGlobalMutex);
#endif //LOG_DEBUG
return;
}
void LogHex(char *pData, size_t size)
{
    size_t i;
    size_t c;
    unsigned int width=0x10;
    char lineStr[128];
   for(i=0; i<size; i+= width) {
        sprintf(lineStr, ” %8.8lX: \0″, (long)i);
        /* show hex to the left */
        for(c = 0; c < width; c++) {
            if(i+c < size)
                sprintf(lineStr+strlen(lineStr), “%02X \0”, pData[i+c]);
            else
                sprintf(lineStr+strlen(lineStr), ” \0″);
        }
        sprintf(lineStr+strlen(lineStr), ” \0″);
        /* show data on the right */
        for(c = 0; (c < width) && (i+c < size); c++) {
            char x = (pData[i+c] >= 0x20 && pData[i+c] < 0x80) ? pData[i+c] : ‘.’;
            sprintf(lineStr+strlen(lineStr), “%c\0”, x);
        }
        sprintf(lineStr+strlen(lineStr), “\n\0”);
        Log(“DEBUG %s”, lineStr); /* newline */
    }
    Log(“DEBUG \n”); /* space line */
}
EasyCurl.h
基于网上代码修改而来的。
#ifndef __EASY_CURL_H__
#define __EASY_CURL_H__
#include <string>
#include <functional>
#include <tr1/memory>
#include <tr1/functional>
using std::string;
class IProgressCallback
{
public:
    virtual bool OnProgressCallback(int nValue) = 0;
};
class EasyCurl
{
public:
    EasyCurl(void);
    ~EasyCurl(void);
    typedef std::tr1::function<void(int)> ProgressFunction;
public:
    /// @brief      HTTP POST请求
    /// @param[in]  strUrl 输入参数,请求的Url地址,如:https://www.baidu.com
    /// @param[in]  strParam 输入参数,使用格式”name=kandy&pwd=1234″
    /// @param[out] strResponse 输出参数,返回的内容
    /// @param[in]  pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
    /// @remark     返回是否Post成功
    /// @return     CURLE_OK,成功!其余失败
    int http_post(const string & strUrl, const string & strParam, string & strResponse, const char * pCaPath = NULL);
    /// @brief      HTTPS GET请求
    /// @param[in]  strUrl 输入参数,请求的Url地址,如:https://www.baidu.com
    /// @param[out] strResponse 输出参数,返回的内容
    /// @param[in]  pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
    /// @remark     返回是否Post成功
    /// @return     CURLE_OK,成功!其余失败
    int http_get(const string & strUrl, string & strResponse, const char * pCaPath = NULL);
    /// @brief      文件下载
    /// @param[in]  url : 要下载文件的url地址
    /// @param[in]  outfilename : 下载文件指定的文件名
    /// @remark
    /// @return     返回0代表成功
    int download_file(const string & strUrl, const string & strFile);
    /// @brief      进度报告处理
    /// @param[in]  func : 函数地址
    /// @remark
    /// @return     void
    void set_progress_function(ProgressFunction func);
    /// @brief      进度报告处理
    /// @param[in]  pCallback : 传入的对象
    /// @remark     使用的类继承于IProgressCallback
    /// @return     void
    void set_progress_callback(IProgressCallback *pCallback);
    //
public:
    void SetDebug(bool bDebug);
protected:
    static int progress_callback(void *pParam, double dltotal, double dlnow, double ultotal, double ulnow);
private:
    bool m_bDebug;
    ProgressFunction    m_updateProgress;
    IProgressCallback   *m_pHttpCallback;
};
#endif //__EASY_CURL_H__
EasyCurl.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
extern “C” {
#include”log.h”
}
#include “EasyCurl.h”
EasyCurl::EasyCurl(void)
: m_bDebug(false)
{
}
EasyCurl::~EasyCurl(void)
{
}
static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
{
    switch(itype){
        case CURLINFO_TEXT:
    Log(“DEBUG %s => %s(): [TEXT], len: %10.10ld bytes (0x%8.8lx), context: \n”, __FILE__, __FUNCTION__, (long)size, (long)size);
            LogHex(pData, size);
            break;
        case CURLINFO_HEADER_IN:
    Log(“DEBUG %s => %s(): [HEADER_IN], len: %10.10ld bytes (0x%8.8lx), context: \n”, __FILE__, __FUNCTION__, (long)size, (long)size);
            LogHex(pData, size);
            break;
        case CURLINFO_HEADER_OUT:
    Log(“DEBUG %s => %s(): [HEADER_OUT], len: %10.10ld bytes (0x%8.8lx), context: \n”, __FILE__, __FUNCTION__, (long)size, (long)size);
            LogHex(pData, size);
            break;
        case CURLINFO_DATA_IN:
    //Log(“DEBUG %s => %s(): [DATA_IN], len: %10.10ld bytes (0x%8.8lx), context: \n”, __FILE__, __FUNCTION__, (long)size, (long)size);
            //LogHex(pData, size);
            break;
        case CURLINFO_DATA_OUT:
    //Log(“DEBUG %s => %s(): [DATA_OUT], len: %10.10ld bytes (0x%8.8lx), context: \n”, __FILE__, __FUNCTION__, (long)size, (long)size);
            //LogHex(pData, size);
            break;
        case CURLINFO_SSL_DATA_IN:
    //Log(“DEBUG %s => %s(): [SSL_DATA_IN], len: %10.10ld bytes (0x%8.8lx), context: \n”, __FILE__, __FUNCTION__, (long)size, (long)size);
            //LogHex(pData, size);
            break;
        case CURLINFO_SSL_DATA_OUT:
    //Log(“DEBUG %s => %s(): [SSL_DATA_OUT], len: %10.10ld bytes (0x%8.8lx), context: \n”, __FILE__, __FUNCTION__, (long)size, (long)size);
            //LogHex(pData, size);
            break;
        default:
    Log(“ERROR %s => %s(): unknown itype: %d, len: %10.10ld bytes (0x%8.8lx), context: \n”, __FILE__, __FUNCTION__, itype, (long)size, (long)size);
            break;
    }
    return 0;
}
static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
    string* str = dynamic_cast<string*>((string *)lpVoid);
    if( NULL == str || NULL == buffer ) {
        return -1;
    }
char* pData = (char*)buffer;
str->append(pData, size * nmemb);
Log(“DEBUG %s => %s(): OnWriteData, len: %10.10ld bytes (0x%8.8lx), context: \n”, __FILE__, __FUNCTION__, (long)size*nmemb, (long)size*nmemb);
    LogHex((char *)buffer, size * nmemb);
    return nmemb;
}
static size_t OnReadData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
    string* str = dynamic_cast<string*>((string *)lpVoid);
    if( NULL == str || NULL == buffer ) {
        return -1;
    }
char* pData = (char*)buffer;
str->append(pData, size * nmemb);
Log(“DEBUG %s => %s(): OnReadData, len: %10.10ld bytes (0x%8.8lx), context: \n”, __FILE__, __FUNCTION__, (long)size*nmemb, (long)size*nmemb);
    LogHex((char *)buffer, size * nmemb);
    return nmemb;
}
/* libcurl write callback function */
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
    size_t written = fwrite(ptr, size, nmemb, stream);
    return written;
    //CAN WRITE data to FILE.
    //FILE* fp = NULL;
    //fp = fopen(“c:\\test.dat”, “ab+”);// must be a, otherwise will recovery pre data.
    //size_t nWrite = fwrite(ptr, nSize, nmemb, fp);
    //fclose(fp);
    //return nWrite;
}
//
int EasyCurl::progress_callback(void *pParam, double dltotal, double dlnow, double ultotal, double ulnow)
{
    EasyCurl* pThis = (EasyCurl*)pParam;
    int nPos = (int)((dlnow / dltotal) * 100);
    if (pThis->m_pHttpCallback) {
        pThis->m_pHttpCallback->OnProgressCallback(nPos);
    }
    if (pThis->m_updateProgress) {
        pThis->m_updateProgress(nPos);
    }
    return 0;
}
//
string globalCurlStrSend;
int EasyCurl::http_post(const string & strUrl, const string & strParam, string & strResponse, const char * pCaPath)
{
    CURLcode res;
    CURL* curl = curl_easy_init();
    if(NULL == curl) {
        return CURLE_FAILED_INIT;
    }
    if(m_bDebug) {
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    }
    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strParam.c_str());
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, OnReadData); //not used, only for PUT
    globalCurlStrSend = “”;
    curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&globalCurlStrSend);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); //for 302, redirect
    curl_easy_setopt(curl, CURLOPT_COOKIEFILE, “”);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
    if(NULL == pCaPath) {
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); //not verify peer cert and peer host
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
    }
    else {
        //default is PEM, so needn’t to set, and can support DER.
        //curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,”PEM”);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
        curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
    }
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); // wait 10 seconds to connect server.
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 100L); //wait 100 seconds to get content from server.
    res = curl_easy_perform(curl);
    if(res != CURLE_OK){ //CURLE_OK is 0
    Log(“ERROR %s => %s(): curl_easy_perform() failed: %s\n”, __FILE__, __FUNCTION__, curl_easy_strerror(res));
        curl_easy_cleanup(curl);
        return res;
    }
    long retcode = 0;
    res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE , &retcode);
    if(res != CURLE_OK){ //CURLE_OK is 0
    Log(“ERROR %s => %s(): curl_easy_getinfo() failed: %s\n”, __FILE__, __FUNCTION__, curl_easy_strerror(res));
        curl_easy_cleanup(curl);
        return res;
    }
    if(retcode == 200 || retcode == 302){ //success
    Log(“DEBUG %s => %s(): curl_easy_getinfo() return code: %ld\n”, __FILE__, __FUNCTION__, retcode);
    }else{ // can return content, but is not wanted content.
    Log(“ERROR %s => %s(): curl_easy_getinfo() return code: %ld\n”, __FILE__, __FUNCTION__, retcode);
        curl_easy_cleanup(curl);
        return -1;
    }
    curl_easy_cleanup(curl);
    return res;
}
//
int EasyCurl::http_get(const string & strUrl, string & strResponse, const char * pCaPath)
{
    CURLcode res;
    CURL* curl = curl_easy_init();
    if(NULL == curl) {
        return CURLE_FAILED_INIT;
    }
    if(m_bDebug) {
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    }
    curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, OnReadData); //not used, only for PUT
    globalCurlStrSend = “”;
    curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&globalCurlStrSend);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); //for 302, redirect
    curl_easy_setopt(curl, CURLOPT_COOKIEFILE, “”);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    if(NULL == pCaPath) {
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); //not verify peer cert and peer host
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
    }
    else {
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
        curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
    }
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 100L);
    res = curl_easy_perform(curl);
    if(res != CURLE_OK){ //CURLE_OK is 0
    Log(“ERROR %s => %s(): curl_easy_perform() failed: %s\n”, __FILE__, __FUNCTION__, curl_easy_strerror(res));
        curl_easy_cleanup(curl);
        return res;
    }
    long retcode = 0;
    res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE , &retcode);
    if(res != CURLE_OK){ //CURLE_OK is 0
    Log(“ERROR %s => %s(): curl_easy_getinfo() failed: %s\n”, __FILE__, __FUNCTION__, curl_easy_strerror(res));
        curl_easy_cleanup(curl);
        return res;
    }
    if(retcode == 200 || retcode == 302){ //success
    Log(“DEBUG %s => %s(): curl_easy_getinfo() return code: %ld\n”, __FILE__, __FUNCTION__, retcode);
    }else{ // can return content, but is not wanted content.
    Log(“ERROR %s => %s(): curl_easy_getinfo() return code: %ld\n”, __FILE__, __FUNCTION__, retcode);
        curl_easy_cleanup(curl);
        return -1;
    }
    curl_easy_cleanup(curl);
    return res;
}
//
int EasyCurl::download_file(const string & strUrl, const string & strFile)
{
    FILE *fp;
    //call curl_easy_init() to get easy interface type pointer.
    CURL *curl = curl_easy_init();
    if (curl) {
        fp = fopen(strFile.c_str(), “wb”);
        CURLcode res = curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
        if (res != CURLE_OK) {
            fclose(fp);
            curl_easy_cleanup(curl);
            return -1;
        }
        res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        if (res != CURLE_OK) {
            fclose(fp);
            curl_easy_cleanup(curl);
            return -1;
        }
        res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        if (res != CURLE_OK) {
            fclose(fp);
            curl_easy_cleanup(curl);
            return -1;
        }
        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
        curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);//set progress function.
        curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this);
        //start to run query.
        res = curl_easy_perform(curl);
        fclose(fp);
        // Check for errors
        if (res != CURLE_OK) {
            curl_easy_cleanup(curl);
            return -1;
        }
        curl_easy_cleanup(curl);// call curl_easy_cleanup() to release memory
    }
    return 0;
}
//
void EasyCurl::set_progress_function(ProgressFunction func)
{
    m_updateProgress = func;
}
//
void EasyCurl::set_progress_callback(IProgressCallback *pCallback)
{
    m_pHttpCallback = pCallback;
}
//
void EasyCurl::SetDebug(bool bDebug)
{
    m_bDebug = bDebug;
}
main.cpp
调用测试:
int main(void)
{
//log init
InitLog();
//loop
EasyCurl easyCurl;
easyCurl.SetDebug(true);
for(;;){
Log(“DEBUG %s => %s(): Enter Main Loop. \n”, __FILE__, __FUNCTION__);
string strUrl = “http://www.baidu.com/”;
string strParam = “id=3435”;
string strResponse = “”; // return content will be saved in this string.
int rtn =easyCurl.http_post(strUrl, strParam, strResponse, NULL);
Log(“DEBUG %s => %s(): http_post return: %d\n”, __FILE__, __FUNCTION__, rtn);
sleep(5);
}
//log uninit
UninitLog();
return0;
}