curl的应用
Posted liyubo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了curl的应用相关的知识,希望对你有一定的参考价值。
1
#include <string> #include <curl/curl.h> #include "cJSON.h" /* 为了通过编译定义的宏 */ #define OUT #define INOUT #define IN #define TMS_LOG0(lLogLevel, ulErrCode, str) #define TMS_LOG1(lLogLevel, ulErrCode, str, str1) #define TMS_LOG2(lLogLevel, ulErrCode, str, str1, str2) typedef unsigned int ULONG_32; typedef unsigned long SIZE_T; /* 类所需要的宏、结构体的定义 */ /** RESTFUL接口HTTP头格式枚举 */ typedef enum tagTMSMethodType { TMS_METHOD_GET = 0, /* HTTP 头GET */ TMS_METHOD_PUT = 1, /* HTTP 头PUT */ TMS_METHOD_POST = 2, /* HTTP 头POST */ TMS_METHOD_DELETE = 3, /* HTTP 头DELETE */ TMS_METHOD_INVALID = 0xFFFFFFFF /* 无效值 */ }TMS_METHOD_TYPE_E; #define TMS_WA_REST_LIBCURL_OUT_TIME (40) /* rest接口POST请求传输超时时间*/ #define TMS_WA_REST_LIBCURL_CONNECT_OUT_TIME (40) /* rest接口POST请求连接超时时间*/ #define TMS_WA_REST_HTTP_CONTENT_TYPE "application/json" /* rest接口POST请求头类型 */ #define TMS_WA_REST_RECV_LEN (1024) /* rest接口POST请求接收消息最大长度 */ #define TMS_WA_REST_RECV_CODE "0" /* REST接口返回正常状态码 */ #define ERR_COMMON_SUCCEED (0) /* 成功通用码 */ #define ERR_COMMON_FAIL (1) /* 失败通用码 */ /* 与DBE交互的Restful接口错误码 */ #define TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE (0x0EEEE000UL) #define TMS_WA_RESTFUL_CURL_UNSUPPORTED_PROTOCOL (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 1) /* 协议不支持 */ #define TMS_WA_RESTFUL_CURL_FAILED_INIT (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 2) /* CURL初始化失败 */ #define TMS_WA_RESTFUL_CURL_URL_MALFORMAT (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 3) /* URL格式错误 */ #define TMS_WA_RESTFUL_CURL_NOT_BUILT_IN (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 4) /* Curl未安装 */ #define TMS_WA_RESTFUL_CURL_COULDNT_RESOLVE_PROXY (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 5) /* 代理解析失败 */ #define TMS_WA_RESTFUL_CURL_COULDNT_RESOLVE_HOST (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 6) /* 解析主机失败 */ #define TMS_WA_RESTFUL_CURL_COULDNT_CONNECT (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 7) /* 链接主机或代理失败 */ #define TMS_WA_RESTFUL_CURL_FTP_WEIRD_SERVER_REPLY (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 8) /* 不确定的FTP服务器 */ #define TMS_WA_RESTFUL_CURO_REMOTE_ACCESS_DENIED (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 9) /* 访问被拒绝 */ #define TMS_WA_RESTFUL_CURL_HTTP_RETURNED_ERROR (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 22) /* 返回的错误代码> = 400 */ #define TMS_WA_RESTFUL_CURL_OPERATION_TIMEDOUT (TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + 28) /* 超时 */ /* TMS_MAC_RestDataRecive回调函数所需的第四个参数 */ typedef struct tagTMSRecvDataInfo { ULONG_32 ulBufferlen; /* 返回信息的Buff长度 */ ULONG_32 ulBufferOffset; /* 返回信息开始位置 */ char *pcBufferAddr; /* 指向接收返回信息的Buffer */ }TMS_RECV_DATA_INFO_S; /* 发送curl网络数据的结构体 */ typedef struct tagSendDataInfo { /* 数据 */ CHAR *pcData; /* 数据发送地址 */ CHAR *pcPostData; /* 数据截止地址 */ CHAR *pcLastData; }TMS_SEND_DATA_INFO_S; /** * 解析返回值的函数样例 \n * @return ULONG_32, * - 成功:ERR_COMMON_SUCCEED * - 失败:见错误码文件 * @note 无 */ ULONG_32 TMS_RestParseReciveValue(char *pszRecvBuffer) { cJSON *poReturnJson = cJSON_Parse(pszRecvBuffer); if (NULL == poReturnJson) { TMS_LOG0(IMOS_ERROR, ERR_COMMON_SYS_FAIL,"Failed to batch insert MAC record,return NULL."); return ERR_COMMON_FAIL; } cJSON *oMsgJson = cJSON_GetObjectItem(poReturnJson, "msg"); if (NULL == oMsgJson) { TMS_LOG0(IMOS_ERROR, ERR_COMMON_SYS_FAIL,"Failed to batch insert MAC record,return NULL."); return ERR_COMMON_FAIL; } std::string oMsg = oMsgJson->valuestring; cJSON *oCodeJson = cJSON_GetObjectItem(poReturnJson, "code"); if (NULL == oCodeJson) { TMS_LOG0(IMOS_ERROR, ERR_COMMON_SYS_FAIL,"Failed to batch insert MAC record,return NULL."); return ERR_COMMON_FAIL; } std::string oCode = oCodeJson->valuestring; /* REST接口状态码(0表示正常,1表示错误)*/ if (TMS_WA_REST_RECV_CODE != oCode) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_SYS_FAIL,"Failed to batch insert MAC record, err msg:%s.", oMsg.c_str()); return ERR_COMMON_FAIL; } return ERR_COMMON_SUCCEED; } /** * @class IMOS_TMS_REST * @brief 通过libcurl 库的POST、GET、PUT、DELETE */ class IMOS_TMS_REST { public: IMOS_TMS_REST(std::string oUrl, TMS_METHOD_TYPE_E ulMethod, char *pcData, ULONG_32(*pfRestParseRecive)(char *)): m_oUrl(oUrl), m_ulMethod(ulMethod), m_pcData(pcData), m_pfRestParseRecive(pfRestParseRecive) { m_stCallBackDataInfo.ulBufferlen = TMS_WA_REST_RECV_LEN; m_stCallBackDataInfo.ulBufferOffset = 0; m_stCallBackDataInfo.pcBufferAddr = m_szRecvBuffer; memset(m_szRecvBuffer, 0, TMS_WA_REST_RECV_LEN); } ~IMOS_TMS_REST() { } public: /** * 发送数据的public接口 \n * @return ULONG_32, * - 成功:ERR_COMMON_SUCCEED * - 失败:见错误码文件 * @note 无 */ ULONG_32 send(); /* 类内工具函数 */ private: /** * REST接口回调函数 * @param [IN] void* ptr 指向返回内容的指针 * @param [IN] size_t size 返回内容单位字节数 * @param [IN] size_t nmemb 返回内容个数 * @param [IN][OUT] void *stream 输入自定义参数 * @return size * nmemb 返回内容单位字节数与返回内容个数的乘积 * @note 无 */ static SIZE_T IMOS_TMS_REST_DataRecive(IN VOID *ptr, IN SIZE_T size, IN SIZE_T nmemb, INOUT VOID *stream); /** * restful接口 libcurl 发送数据函数 * @param [in] VOID * pContents 发送到数据所在缓冲区 * @param [in] ULONG_32 ulSize 数据长度 * @param [in] ULONG_32 ulMemNum 返回内容个数 * @param [in] VOID *pStream 用户自定义要写入的指针 * @return ULONG_32 返回实际传出的数据实际大小 * @note */ static ULONG_32 TMS_ReadCallBack(IN VOID *pContents, IN ULONG_32 ulSize, IN ULONG_32 ulMemCount, OUT VOID *pStream); /** * 发送数据 \n * @return ULONG_32, * - 成功:ERR_COMMON_SUCCEED * - 失败:见错误码文件 * @note 无 */ ULONG_32 IMOS_TMS_Send(); private: /* 构造回调函数所需的第四个参数 */ TMS_RECV_DATA_INFO_S m_stCallBackDataInfo; /* 发送的数据 */ char *m_pcData; /* URL */ std::string m_oUrl; /* 传输方式 */ ULONG_32 m_ulMethod; /* 存储接收返回信息的Buffer,注意大小 */ char m_szRecvBuffer[TMS_WA_REST_RECV_LEN]; /* 用来指向类外成员函数,用作返回值的解析 */ ULONG_32(*m_pfRestParseRecive)(char *); }; /** * REST接口批量写入终端特征移动采集设备轨迹信息到大数据public接口 \n * @return ULONG_32, * - 成功:ERR_COMMON_SUCCEED * - 失败:见错误码文件 * @note 无 */ ULONG_32 IMOS_TMS_REST::send() { /* 发送数据 */ ULONG_32 ulRet = IMOS_TMS_Send(); if (ERR_COMMON_SUCCEED != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_SYS_FAIL,"Failed to batch insert MAC record, err code=%u.", ulRet); return ERR_COMMON_FAIL; } /* 解析REST接口返回值 */ ulRet = m_pfRestParseRecive(m_szRecvBuffer); if (ERR_COMMON_SUCCEED != ulRet) { TMS_LOG0(IMOS_ERROR, ulRet, "Failed to batch insert MAC record."); return ERR_COMMON_FAIL; } return ERR_COMMON_SUCCEED; } /** * REST接口回调函数 * @param [IN] void* ptr 指向返回内容的指针 * @param [IN] size_t size 返回内容单位字节数 * @param [IN] size_t nmemb 返回内容个数 * @param [IN][OUT] void *stream 输入自定义参数 * @return size * nmemb 返回内容单位字节数与返回内容个数的乘积 * @note 无 */ SIZE_T IMOS_TMS_REST::IMOS_TMS_REST_DataRecive(IN VOID *ptr, IN SIZE_T size, IN SIZE_T nmemb, INOUT VOID *stream) { /* 入参检测 */ if ((NULL == ptr) || (NULL == stream)) { TMS_LOG0(IMOS_ERROR, ERR_COMMON_INVALID_PARAM, "Failed: Invalid param."); return ERR_COMMON_FAIL; } /* 进行内存是否越界的判断 */ TMS_RECV_DATA_INFO_S *pstRevcDataInfo = (TMS_RECV_DATA_INFO_S *)stream; ULONG_32 ulTotalBytes = size * nmemb; if ((pstRevcDataInfo->ulBufferOffset + ulTotalBytes) >= pstRevcDataInfo->ulBufferlen) { TMS_LOG0(IMOS_ERROR, ERR_COMMON_INVALID_PARAM, "Current data length greater data buffer lenth."); return ERR_COMMON_FAIL; } /* 进行内存拷贝 */ memcpy(pstRevcDataInfo->pcBufferAddr + pstRevcDataInfo->ulBufferOffset, ptr, ulTotalBytes); pstRevcDataInfo->ulBufferOffset += ulTotalBytes; return ulTotalBytes; } /** * restful接口 libcurl 发送数据函数 * @param [in] VOID * pContents 发送到数据所在缓冲区 * @param [in] ULONG_32 ulSize 数据长度 * @param [in] ULONG_32 ulMemNum 返回内容个数 * @param [in] VOID *pStream 用户自定义要写入的指针 * @return ULONG_32 返回实际传出的数据实际大小 * @note */ ULONG_32 IMOS_TMS_REST::TMS_ReadCallBack ( IN VOID *pContents, IN ULONG_32 ulSize, IN ULONG_32 ulMemCount, OUT VOID *pStream ) { ULONG_32 ulTotalBytes = 0; TMS_SEND_DATA_INFO_S *pstSendDataInfo = (TMS_SEND_DATA_INFO_S *)pStream; /* 已发送完全 */ if (pstSendDataInfo->pcPostData >= pstSendDataInfo->pcLastData) { return 0; } if ((0 == ulSize) || (0 == ulMemCount) || (ulSize * ulMemCount) < 1) { TMS_LOG0(IMOS_ERROR, ERR_COMMON_INVALID_PARAM, "Send Data Error."); return 0; } ulTotalBytes = pstSendDataInfo->pcLastData - pstSendDataInfo->pcPostData; if (ulTotalBytes > (ulSize * ulMemCount)) { ulTotalBytes = ulSize * ulMemCount; } memcpy(pContents, pstSendDataInfo->pcPostData, ulTotalBytes); pstSendDataInfo->pcPostData += ulTotalBytes; TMS_LOG1(IMOS_INFO, ERR_COMMON_SUCCEED, "Send Len = %u", ulTotalBytes); return ulTotalBytes; } /** * 大数据中批量插入终端特征移动采集设备轨迹信息(Json数据) \n * @return ULONG_32, * - 成功:ERR_COMMON_SUCCEED * - 失败:见错误码文件 * @note 无 */ ULONG_32 IMOS_TMS_REST::IMOS_TMS_Send() { if (NULL == m_pcData) { TMS_LOG0(IMOS_ERROR, ERR_COMMON_INVALID_PARAM, "Failed: Invalid param m_poRoot"); return ERR_COMMON_FAIL; } /* 构造CURL */ CURL *poCurl = NULL; CURLcode ulRet = CURLE_OK; struct curl_slist *pstHttpHeader = NULL; /* 初始化CURL指针 */ poCurl = curl_easy_init(); if (NULL == poCurl) { TMS_LOG0(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to Rest curl_easy_init"); return ERR_COMMON_FAIL; } /* 构造发送回调函数所需的参数 */ TMS_SEND_DATA_INFO_S stSendDataInfo; memset(&stSendDataInfo, 0, sizeof(TMS_SEND_DATA_INFO_S)); if (NULL != m_pcData) { stSendDataInfo.pcData = (CHAR *)m_pcData; stSendDataInfo.pcPostData = (CHAR *)m_pcData; stSendDataInfo.pcLastData = stSendDataInfo.pcPostData + strlen(m_pcData); } do { /* 设置传输超时时间 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_TIMEOUT, TMS_WA_REST_LIBCURL_OUT_TIME); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_TIMOUT, enCurlRet = %d.", (ULONG_32)ulRet); break; } /* 设置连接超时时间 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_CONNECTTIMEOUT, TMS_WA_REST_LIBCURL_CONNECT_OUT_TIME); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CONNECT TIME OUT, enCurlRet = %d.", (ULONG_32)ulRet); break; } /* 设置超时不产生信号 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_NOSIGNAL, 1L); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_NOSIGNAL, enCurlRet = %d.", (ULONG_32)ulRet); break; } switch (m_ulMethod) { case TMS_METHOD_DELETE: { /* 设置为DELETE请求 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_CUSTOMREQUEST, "DELETE"); break; } case TMS_METHOD_PUT: { /* 设置为PUT请求 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_PUT, 1); break; } case TMS_METHOD_GET: { /* 设置为GET请求 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_CUSTOMREQUEST, "GET"); break; } default: { /* 设置为post请求 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_POST, 1); break; } } if (CURLE_OK != ulRet) { TMS_LOG2(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set Method(%u), enCurlRet = %d.", m_ulMethod, (ULONG_32)ulRet); break; } /* 设置post的url */ ulRet = curl_easy_setopt(poCurl, CURLOPT_URL, m_oUrl.c_str()); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_URL, enCurlRet = %d.", (ULONG_32)ulRet); break; } /* 设置http头信息 */ std::string oRestHttpContentType = "Content-Type: "; oRestHttpContentType += TMS_WA_REST_HTTP_CONTENT_TYPE; pstHttpHeader = curl_slist_append(pstHttpHeader, oRestHttpContentType.c_str()); if(NULL == pstHttpHeader) { TMS_LOG0(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call curl_slist_append, maybe out of memeroy."); break; } ulRet = curl_easy_setopt(poCurl, CURLOPT_HTTPHEADER, pstHttpHeader); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_HTTPHEADER, enCurlRet = %d.", (ULONG_32)ulRet); break; } /* 设置post的数据 */ if (TMS_METHOD_POST == m_ulMethod) { /* 设置post的数据 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_POSTFIELDS, m_pcData); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_POSTFIELDS, enCurlRet = %d.", (ULONG_32)ulRet); break; } } else if (TMS_METHOD_POST != m_ulMethod) { /* 设置PUT的数据 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_READFUNCTION, TMS_ReadCallBack); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_READFUNCTION, enCurlRet = %d.", (ULONG_32)ulRet); break; } ulRet = curl_easy_setopt(poCurl, CURLOPT_UPLOAD, true); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_UPLOAD, enCurlRet = %d.", (ULONG_32)ulRet); break; } ulRet = curl_easy_setopt(poCurl, CURLOPT_READDATA, &stSendDataInfo); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_READDATA, enCurlRet = %d.", (ULONG_32)ulRet); break; } /* 当向服务器上传文件时,该选项用来告诉 curl 库期望上传的文件的大小 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)(stSendDataInfo.pcLastData - stSendDataInfo.pcPostData)); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_READDATA, enCurlRet = %d.", (ULONG_32)ulRet); break; } } else { /* 设置BODY为空 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_NOBODY, false); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_NOBODY, enCurlRet = %d.", (ULONG_32)ulRet); break; } } if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set CURLOPT_POSTFIELDS, enCurlRet = %d.", (ULONG_32)ulRet); break; } /* 设置post的回调函数 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_WRITEFUNCTION, IMOS_TMS_REST_DataRecive); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set FuncCallBack, enCurlRet = %d.", (ULONG_32)ulRet); break; } /* 设置post的返回包的处理函数的第四个参数 */ ulRet = curl_easy_setopt(poCurl, CURLOPT_WRITEDATA, &m_stCallBackDataInfo); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call set Param for FunCallBack, enCurlRet = %d.", (ULONG_32)ulRet); break; } /* 完成请求 */ ulRet = curl_easy_perform(poCurl); if (CURLE_OK != ulRet) { TMS_LOG1(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to curl_easy_perform, enCurlRet = %d.", (ULONG_32)ulRet); break; } } while (0); if(NULL != pstHttpHeader) { curl_slist_free_all(pstHttpHeader); } /* 结束会话 */ curl_easy_cleanup(poCurl); if (CURLE_OK != ulRet) { TMS_LOG0(IMOS_ERROR, ERR_COMMON_FAIL, "Failed to call the REST ULONG_32erface!"); return TMS_WA_RESTFUL_CURL_ERR_FAILED_BASE + ulRet; } return ERR_COMMON_SUCCEED; } ULONG_32 main() { char ppp[48] = {"[email protected]#201709111634158"}; std::string URL = "http://192.169.12.239:61005/VIID"; TMS_METHOD_TYPE_E ulMethod = TMS_METHOD_POST; IMOS_TMS_REST fdf(URL, ulMethod, ppp, TMS_RestParseReciveValue ); fdf.send(); system("pause"); return 0; }
111
以上是关于curl的应用的主要内容,如果未能解决你的问题,请参考以下文章
CentOS yum 命令出现 [Errno 14] curl#6 - "Couldn't resolve host ..." 的解决方法(代码片段
有啥方法可以让 curl 连接并让我在输入时输入和发送身体片段?
如何使用 Swift 使用此代码片段为 iOS 应用程序初始化 SDK?
每当我运行我的片段时,这行代码 mapFragment.setRetainInstance(true);正在崩溃我的应用程序? [关闭]