由淺入深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中默認加上的雙引號; 
*/
#define X_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中取出這次交互返回的數據。
*/
static size_t cb_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)return 0;  /* 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 ...");struct curl_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中默認加上的雙引號; */
#define X_LOG_DEBUG(Z, X...) \printf("[%s %s] [%s.%d] [%s] [DEBUG] " Z "\n", __DATE__, __TIME__, __FILE__, __LINE__, __FUNCTION__, ##X)#define MAX_UTMP_TOKEN_SIZE 8192typedef struct http_response_s {char *response;size_t size;
} http_response;typedef struct http_request_s {char *request;size_t size;
} http_request;http_response* http_post(char* url, char* token, char* payload);#endif

測試調用

int main(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 11 2023 10:20:02] [src/xhttp.c.37] [http_post] [DEBUG] "libcurl curl_easy_setopt start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.42] [http_post] [DEBUG] "libcurl curl_easy_setopt CURLOPT_HTTPHEADER start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.55] [http_post] [DEBUG] "libcurl curl_easy_setopt CURLOPT_USERAGENT start ..."
[Aug 11 2023 10:20:02] [src/xhttp.c.61] [http_post] [DEBUG] "libcurl curl_easy_setopt CURLOPT_POSTFIELDSIZE/CURLOPT_POSTFIELDS start ..."
[Aug 11 2023 10: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"

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/37802.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/37802.shtml
英文地址,請注明出處:http://en.pswp.cn/news/37802.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python中單引號、雙引號和三引號的區別

① 單引號和雙引號主要用來表示字符串 # 單引號 astr = Python print(type(astr)) # <class str># 雙引號"" bstr = "Python" print(type(bstr)) # <class str> str1 = I\m a big fan of Python. print(str1) # Im a big fan of Python.s…

[HDLBits] Exams/m2014 q4d

Implement the following circuit: module top_module (input clk,input in, output out);always(posedge clk) beginout<out^in;end endmodule直接寫out^in就行

Vue 使用 vite 創建項目

vite 是新一代前端構建工具&#xff0c;和 webpack 類似。 vite 的啟動速度更快。在開發環境中&#xff0c;不需要打包就可以直接運行。 vite 的更新速度更快。當修改內容后&#xff0c;不需要刷新瀏覽器&#xff0c;頁面就會實時更新。 vite 完全是按需編譯。它只會編譯需要…

【考研數學】高等數學第三模塊——積分學 | Part II 定積分(反常積分及定積分應用)

文章目錄 前言三、廣義積分3.1 斂散性概念&#xff08;一&#xff09;積分區間為無限的廣義積分&#xff08;二&#xff09;積分區間有限但存在無窮間斷點 3.2 斂散性判別法 四、定積分應用寫在最后 前言 承接前文&#xff0c;梳理完定積分的定義及性質后&#xff0c;我們進入…

企業網盤 vs 傳統存儲設備:為何云存儲成為首選?

企業網盤的出現為企業提供了新的存儲方式&#xff0c;相較于傳統的存儲設備&#xff0c;為何越來越多的企業選擇了云存儲呢&#xff1f; 一、存儲成本 在企業數據存儲方面&#xff0c;成本是企業重要的考量因素。企業網盤是基于云存儲技術的存儲工具&#xff0c;因此它比傳統的…

基于DBN的偽測量配電網狀態估計,DBN的詳細原理

目錄 背影 DBN神經網絡的原理 DBN神經網絡的定義 受限玻爾茲曼機(RBM) DBN的偽測量配電網狀態估計 基本結構 主要參數 數據 MATALB代碼 結果圖 展望 背影 DBN是一種深度學習神經網絡,擁有提取特征,非監督學習的能力,是一種非常好的分類算法,本文將DBN算法偽測量配電網…

Netty:ByteBuf的資源釋放方法

說明 io.netty.buffer.ByteBuf實現了io.netty.util.ReferenceCounted接口&#xff0c;需要顯式釋放。當ByteBuf被實例化后&#xff0c;它的引用計數是1。 調用ByteBuf對象的release方法釋放&#xff1a; ByteBuf的release()方法使引用計數減少1。只有當執行以后引用計數減少…

OpenZFS 2.2 發布 RC3,支持 Linux 6.4

導讀之前的 OpenZFS 2.2 候選版本已致力于實現與 Linux 6.4 內核的兼容性&#xff0c;而在 2.2-rc3 中&#xff0c;Linux 6.4 支持的元跟蹤器已標記為已完成。 OpenZFS 2.2 發布了第 3 個 RC 版本。 之前的 OpenZFS 2.2 候選版本已致力于實現與 Linux 6.4 內核的兼容性&#x…

Vue3 引用第三方Swiper內容觸摸滑動簡單應用

去官網查看更多教程→&#xff1a;Swiper官網 → 點擊教程在vue中使用Swiper→ 在Vue中使用Swiper cd 到項目 安裝Swiper&#xff1a; cnpm install --save swiper 安裝指定版本 cnpm install --save swiper8.1.6 9.4.1 10.1.0…

SpringBoot-Hello World

SpringBootWeb快速入門 創建Springboot工程&#xff0c;并勾選web開發相關依賴定義HelloController類&#xff0c;添加方法hello&#xff0c;并添加相關注釋運行測試 創建新的SpringBoot項目 幾個注意的點&#xff1a; Name&#xff1a;基本上不用管&#xff0c;會根據下面的Ar…

關于elementui的input的autocomplete的使用

項目中需要實現搜索框搜索時能自動提示可選項的功能&#xff0c;elementui的input組件有已經封裝好的el-autocomplete可以使用&#xff0c;但是在使用中發現一些問題&#xff0c;記錄一下 基礎使用 // html部分 <el-autocompletev-model"name":fetch-suggestion…

大數據課程I3——Kafka的消息流與索引機制

文章作者郵箱:yugongshiye@sina.cn 地址:廣東惠州 ▲ 本章節目的 ? 掌握Kafka的消息流處理; ? 掌握Kafka的索引機制; ? 掌握Kafka的消息系統語義; 一、Kafka消息流處理 1. Producer 寫入消息 流程說明: 1. producer 要向Kafka生產消息,需要先通過…

EditPlus連接Linux系統遠程操作文件

EditPlus是一套功能強大的文本編輯器&#xff01; 1.File ->FTP->FTP Settings&#xff1b; 2.Add->Description->FTP server->Username->Password->Subdirectory->Advanced Options 注意&#xff1a;這里的Subdirectory設置的是以后上傳文件的默認…

20230814讓惠普(HP)銳14 新AMD銳龍電腦不聯網進WIN11進系統

20230814讓惠普(HP)銳14 新AMD銳龍電腦不聯網進WIN11進系統 2023/8/14 17:19 win11系統無法跳過聯網 https://www.xpwin7.com/jiaocheng/28499.html Win11開機聯網跳過不了怎么辦&#xff1f;Win11開機聯網跳過不了解決方法 Win11開機聯網跳過不了怎么辦&#xff1f;Win11開機…

Unity框架學習--5 事件中心管理器

作用&#xff1a;訪問其它腳本時&#xff0c;不直接訪問&#xff0c;而是通過發送一條“命令”&#xff0c;讓監聽了這條“命令”的腳本自動執行對應的邏輯。 原理&#xff1a; 1、讓腳本向事件中心添加事件&#xff0c;監聽對應的“命令”。 2、發送“命令”&#xff0c;事件…

【Sklearn】基于支持向量機算法的數據分類預測(Excel可直接替換數據)

【Sklearn】基于支持向量機算法的數據分類預測(Excel可直接替換數據) 1.模型原理1.1 數學模型1.2 模型原理2.模型參數3.文件結構4.Excel數據5.下載地址6.完整代碼7.運行結果1.模型原理 支持向量機(Support Vector Machine,SVM)是一種用于分類和回歸的監督學習算法,其基本…

【Git】安裝以及基本操作

目錄 一、初識Git二、 在Linux底下安裝Git一&#xff09;centOS二&#xff09;Ubuntu 三、 Git基本操作一&#xff09; 創建本地倉庫二&#xff09;配置本地倉庫三&#xff09;認識工作區、暫存區、版本庫四&#xff09;添加文件五&#xff09;查看.git文件六&#xff09;修改文…

基于docker部署的Selenium Grid分布式自動化測試

01、什么是Selenium Grid Selenium Grid是Selenium套件的一部分&#xff0c;它專門用于并行運行多個測試用例在不同的瀏覽器、操作系統和機器上。 Selenium Grid有兩個版本——老版本Grid 1和新版本Grid 2。我們只對新版本做介紹&#xff0c;因為Selenium團隊已經逐漸遺棄老版…

docker容器管理

創建容器&#xff1a; docker run --name 容器名 -d -p 端口1:端口2 –name :是啟動容器時&#xff0c;給容器定義的名稱&#xff0c;不使用該參數時&#xff0c;容器啟動成功之后&#xff0c;會生成隨機名稱 -d &#xff1a;代表容器處于后臺yunx -p &#xff1a;指定容器的端…

第一次參加計算機會議報告注意事項以及心得

計算機會議參會報告 注意事項參會前參會中參會后 參會心得 注意事項 接下來的會議注意事項分為&#xff1a;&#xff08;1&#xff09;參會前&#xff0c;&#xff08;2&#xff09;參會中&#xff0c;&#xff08;3&#xff09;參會后 參會前 參會前&#xff0c;一般被邀請…