0


由浅入深C系列五:使用libcurl进行基于http get/post模式的C语言交互应用开发

使用libcurl进行基于http get/post模式的C语言交互应用开发

简介

大多数在linux下的开发者,都会用到curl这个命令行工具。对于进行restful api的测试等,非常方便。其实,这个工具还提供了一个C的开发库,可以很方便的在C语言开发环境下完成基于http的请求和响应交互,高效的开发基于http/smtp等的网络应用程序

/* 2023-08-14 更新宏定义 
    1. 使用可变参数,支持多项输出; 
    2. 去除Z中默认加上的双引号; 
*/#defineX_LOG_DEBUG(Z, X...)\printf("[%s %s] [%s.%d] [%s] [DEBUG] "Z "\n",__DATE__,__TIME__,__FILE__,__LINE__, __FUNCTION__,##X)

环境准备

下载并安装curl的开发包

yum install libcurl-devel.x86_64

在线资源

开发过程中主要参考CURL官方介绍及API参考文档 | link

示例代码

多余的话就不多说了,直接上示例代码,通过代码中的注释来说明开发过程。

#include<stdlib.h>#include<stdio.h>#include<string.h>#include"../include/xhttp.h"/*
-  这个是一个回调函数,主要用于curl在执行过程中,当有被请求的数据到达时,被调用来向-curl_easy_setopt设置的chunk中写入数据。
  这个回调函数在curl_easy_perform执行完成前会被调用多次。当执行完成后,从chunk中取出这次交互返回的数据。
*/staticsize_tcb_write_data(void*data,size_t size,size_t nmemb,void*clientp){size_t realsize = size * nmemb;
    http_response *mem =(http_response *)clientp;char*ptr =realloc(mem->response, mem->size + realsize +1);if(ptr ==NULL)return0;/* out of response_st! */
 
    mem->response = ptr;memcpy(&(mem->response[mem->size]), data, realsize);
    mem->size += realsize;
    mem->response[mem->size]=0;return realsize;}/*
  这个是向外发布的一个函数,调用的方式示例如下:
  char* payload = "{\"code\":\"\",\"codeUuid\":\"\",\"loginName\":\"user@domain\",\"loginPwd\":\"xxxxxxxx\"}";
  http_response *resp = http_post("https://local.domain/admin-api/session/login", NULL, payload);
  使用完返回数据后,记得释放resp->reesponse,避免内存漏。
*/
http_response*http_post(char* url,char* token,char* payload){
    http_response chunk ={0};/* 设置curl上下文,对curl实例进行初始化 */curl_global_init(CURL_GLOBAL_ALL);
    CURL *curl =curl_easy_init();
    CURLcode res;if(curl){X_LOG_DEBUG("%s","libcurl curl_easy_setopt start ...");/* 设置curl各个参数: 请求地址 */curl_easy_setopt(curl, CURLOPT_URL, url);/* 设置curl各个参数: 请求方式为post */curl_easy_setopt(curl, CURLOPT_POST,1L);/* 设置curl各个参数: http中的请求头部分的内容 */X_LOG_DEBUG("%s","libcurl curl_easy_setopt CURLOPT_HTTPHEADER start ...");structcurl_slist*list ={0};
        list =curl_slist_append(NULL,"Content-Type: application/json;charset=utf8");
        list =curl_slist_append(list,"routeurl: /project/project-list");/* 设置curl各个参数: 可选部分,如果请求中要求token,可以设置上 */if(token !=NULL){char* x_access_token_str =(char*)malloc( MAX_UTMP_TOKEN_SIZE );sprintf(x_access_token_str,"x-access-token: %s", token);X_LOG_DEBUG("%s", x_access_token_str);
            list =curl_slist_append(list, x_access_token_str);}curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);X_LOG_DEBUG("%s","libcurl curl_easy_setopt CURLOPT_USERAGENT start ...");/* some servers do not like requests that are made without a user-agent 
            field, so we provide one */curl_easy_setopt(curl, CURLOPT_USERAGENT,"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0");/* 设置curl各个参数: http的请求体部分,主要是请求中携带的数据 *//* POST data */X_LOG_DEBUG("%s","libcurl curl_easy_setopt CURLOPT_POSTFIELDSIZE/CURLOPT_POSTFIELDS start ...");X_LOG_DEBUG("request body data is:%s", payload);X_LOG_DEBUG("request body len is:%d",strlen(payload));/* size of the POST data */curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,strlen(payload));/* pass in a pointer to the data - libcurl will not copy */curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);/* 设置curl各个参数: 重要部分,设置了返回值的回调函数和返回值的内存放置区域 *//* RECEIVE DATA */X_LOG_DEBUG("%s","libcurl curl_easy_setopt CURLOPT_WRITEFUNCTION/CURLOPT_WRITEDATA start ...");/* send all data to this function  */curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb_write_data);/* we pass our 'chunk' struct to the callback function */curl_easy_setopt(curl, CURLOPT_WRITEDATA,(void*)&chunk);X_LOG_DEBUG("%s","libcurl curl_easy_setopt successfully complete ...");/* 执行curl请求,并获取返回值:CURLE_OK,表示执行成功 */X_LOG_DEBUG("%s","libcurl curl_easy_perform start ...");
        res =curl_easy_perform(curl);X_LOG_DEBUG("%s","libcurl curl_easy_perform successfully complete ...");if(res != CURLE_OK){fprintf(stderr,"curl_easy_perform() is failed: %s",curl_easy_strerror(res));curl_slist_free_all(list);/* free the list again */curl_easy_cleanup(curl);}else{/* 处理curl返回的数据 */X_LOG_DEBUG("chunk size %d", chunk.size);

            http_response response ={0};
            response.response =(char*)malloc(1048576*5);memset(response.response,0, chunk.size+1);memcpy(response.response, chunk.response, chunk.size+1);
            response.size = chunk.size;/* remember to free the buffer */free(chunk.response);curl_slist_free_all(list);/* free the list again */curl_global_cleanup();return&response;}}}

引用的头文件如下:

#ifndef__X_HTTP_H__#define__X_HTTP_H__#include<stdlib.h>#include<curl/curl.h>/* 更新宏定义 1. 使用可变参数,支持多项输出; 2. 去除Z中默认加上的双引号; */#defineX_LOG_DEBUG(Z, X...)\printf("[%s %s] [%s.%d] [%s] [DEBUG] "Z "\n",__DATE__,__TIME__,__FILE__,__LINE__, __FUNCTION__,##X)#defineMAX_UTMP_TOKEN_SIZE8192typedefstructhttp_response_s{char*response;size_t size;} http_response;typedefstructhttp_request_s{char*request;size_t size;} http_request;

http_response*http_post(char* url,char* token,char* payload);#endif

测试调用

intmain(int argc,char** argv){char* payload ="{\"code\":\"\",\"codeUuid\":\"\",\"loginName\":\"user@domain\",\"loginPwd\":\"xxxxxxxx\"}";
    http_response *resp =http_post("https://local.domain/admin-api/session/login",NULL, payload);printf("http_response [%d] is: %s\n", resp->size, resp->response);char*tokenVal =strstr(resp->response,"xaccessToken");int end =strlen(tokenVal);*(tokenVal + end-2)=0;char** token_arr;__strtok_r(tokenVal,":", token_arr);char* replacementKey =strtrim(token_arr[0],'\"');exit(0)}

运行结果

[Aug 11202310:20:02][src/xhttp.c.37][http_post][DEBUG]"libcurl curl_easy_setopt start ..."[Aug 11202310:20:02][src/xhttp.c.42][http_post][DEBUG]"libcurl curl_easy_setopt CURLOPT_HTTPHEADER start ..."[Aug 11202310:20:02][src/xhttp.c.55][http_post][DEBUG]"libcurl curl_easy_setopt CURLOPT_USERAGENT start ..."[Aug 11202310:20:02][src/xhttp.c.61][http_post][DEBUG]"libcurl curl_easy_setopt CURLOPT_POSTFIELDSIZE/CURLOPT_POSTFIELDS start ..."[Aug 11202310:20:02][src/xhttp.c.62][http_post][DEBUG]"request body data is:{"code":"","codeUuid":"","loginName":"user@domain","loginPwd":"xxxxxxxx"}"
[Aug 11 2023 10:20:02] [src/xhttp.c.63] [http_post] [DEBUG] "request body len is:75"
[Aug 11 2023 10:20:02] [src/xhttp.c.70] [http_post] [DEBUG] "libcurl curl_easy_setopt CURLOPT_WRITEFUNCTION/CURLOPT_WRITEDATA start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.76] [http_post] [DEBUG] "libcurl curl_easy_setopt successfully complete ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.79] [http_post] [DEBUG] "libcurl curl_easy_perform start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.81] [http_post] [DEBUG] "libcurl curl_easy_perform successfully complete ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.90] [http_post] [DEBUG] "chunk size 6693"
标签: c语言 http 交互

本文转载自: https://blog.csdn.net/promaster/article/details/132224068
版权归原作者 招财猫_Martin 所有, 如有侵权,请联系我们删除。

“由浅入深C系列五:使用libcurl进行基于http get/post模式的C语言交互应用开发”的评论:

还没有评论