linux下的http請求有許多種方式,其中curl庫是C語言封裝的一個強大的庫,使用curl比封裝socket更加方便。cJSON是一個小型的json封裝庫,可以把數據封裝成json格式。本文介紹了這兩種技術,并通過此技術完成了Linux下的http請求,同時把代碼封裝到quagga下,quagga運行時可以正常創建數據到ONOS。
curl命令是一個功能強大的網絡工具,它能夠通過http、ftp等方式下載文件,也能夠上傳文件。curl命令使用了libcurl庫來實現,libcurl庫常用在C程序中用來處理HTTP請求,curlpp是libcurl的一個C++封裝,這幾個東西可以用在抓取網頁、網絡監控等方面的開發,而curl命令可以幫助來解決開發過程中遇到的問題。本文檔就是使用curl完成http請求。
應用程序在使用libcurl之前,必須先初始化libcurl。libcurl只需初始化一次。可以使用以下語句進行初始化:
curl_global_init();
curl_global_init()接收一個參數,告訴libcurl如何初始化。參數CURL_GLOBAL_ALL 會使libcurl初始化所有的子模塊和一些默認的選項,通常這是一個比較好的默認參數值。還有兩個可選值:
CURL_GLOBAL_WIN32
只能應用于Windows平臺。它告訴libcurl初始化winsock庫。如果winsock庫沒有正確地初始化,應用程序就不能使用socket。在應用程序中,只要初始化一次即可。
CURL_GLOBAL_SSL
如果libcurl在編譯時被設定支持SSL,那么該參數用于初始化相應的SSL庫。同樣,在應用程序中,只要初始化一次即可。
libcurl有默認的保護機制,如果在調用curl_easy_perform時它檢測到還沒有通過curl_global_init進行初始 化,libcurl會根據當前的運行時環境,自動調用全局初始化函數。但必須清楚的是,讓系統自已初始化不是一個好的選擇。
當應用程序不再使用libcurl的時候,應該調用curl_global_cleanup來釋放相關的資源。在程序中,應當避免多次調用curl_global_init和curl_global_cleanup。它們只能被調用一次。
libcurl中被稱為easy interface的api函數,所有這些函數都是有相同的前綴:curl_easy 。
要使用easyinterface,首先必須創建一個easy handle,easy handle用于執行每次操作。基本上,每個線程都應該有自己的easy handle用于數據通信(如果需要的話)。千萬不要在多線程之間共享同一個easy handle。下面的函數用于獲取一個easy handle:
CURL *easy_handle =curl_easy_init();
在easyhandle上可以設置屬性和操作(action)。easy handle就像一個邏輯連接,用于接下來要進行的數據傳輸。
使用curl_easy_setopt函數可以設置easy handle的屬性和操作,這些屬性和操作控制libcurl如何與遠程主機進行數據通信。一旦在easy handle中設置了相應的屬性和操作,它們將一直作用該easyhandle。也就是說,重復使用easy hanle向遠程主機發出請求,先前設置的屬性仍然生效。
easy handle的許多屬性使用字符串(以/0結尾的字節數組)來設置。通過curl_easy_setopt函數設置字符串屬性時,libcurl內部會自動拷貝這些字符串,所以在設置完相關屬性之后,字符串可以直接被釋放掉(如果需要的話)。
后面章節會根據http的get和post接口對常用的easy handle函數進行說明。
cJSON是在C語言中解析JSON的開源庫,在cJSON中,一個key-value鍵值對被解析并存放在一個cJSON結構體變量中,其value取值集為:FALSE,TRUE,NULL,NUMBER,STRING,OBJECT,ARRAY。cJOSN庫,僅有兩個文件cJSON.c和cJSON.h。
下面使用cJSON組裝以下json數據
{
"mac": "46:E4:3C:A4:11:12",
"vlan": "-1",
"ipAddresses": ["222.222.233.2"],
"location": {
"elementId": "of:0000001e08000fe3",
"port": "31"
}
}
代碼如下:
//創建一個object
cJSON *root =cJSON_CreateObject();
cJSON_AddItemToObject(root,"mac",cJSON_CreateString("46:E4:3C:A4:13:12"));
cJSON_AddStringToObject(root,"vlan","-1");
cJSON*array = NULL;
cJSON_AddItemToObject(root,"ipAddresses",array=cJSON_CreateArray());
cJSON_AddItemToArray(array,cJSON_CreateString("192.168.10.2"));
//創建一個子object,將此object添加到root中
cJSON*location = NULL;
cJSON_AddItemToObject(root,"location",location=cJSON_CreateObject());
cJSON_AddStringToObject(location,"elementId","of:0000001e08000fe3");
cJSON_AddStringToObject(location,"port","31");
//將json結構格式化到緩沖區
char*buf = cJSON_PRint(root);
//執行http請求函數
http_client_thttp_read_client;
http_client_read_init(&http_read_client,temp, buf);
//數據使用完之后,把內存釋放掉
cJSON_Delete(json);
free(buf);
int http_client_read_init(http_client_t*http_client, const char *url, char *szJsonData)
{
if (!url) {
return -1;
}
//初始化libcurl,設置默認參數
CURLcode return_code = curl_global_init(CURL_GLOBAL_ALL);
if (CURLE_OK != return_code) {
printf("initlibcurl failed./n");
return -1;
}
//獲取easy handle
http_client->handle = curl_easy_init();
if (!http_client->handle) {
return -1;
}
//通過CURLOPT_URL屬性設置url
curl_easy_setopt(http_client->handle, CURLOPT_URL, url);
//通過CURLOPT_HTTPHEADER定義http消息的header
struct curl_slist *plist = NULL;
plist = curl_slist_append(plist,
"Content-Type:application/json");
curl_easy_setopt(http_client->handle, CURLOPT_HTTPHEADER, plist);
printf("Thejson is: %s/n", szJsonData);
//通過CURLOPT_POSTFIELDS設置要POST的數據
curl_easy_setopt(http_client->handle,CURLOPT_POSTFIELDS, szJsonData);
//通過CURLOPT_USERPWD屬性來設置用戶名與密碼。參數是”user:passWord “的字符串
curl_easy_setopt(http_client->handle,CURLOPT_USERPWD, "karaf:karaf");
//使用curl_easy_perform執行上傳數據
curl_easy_perform(http_client->handle);
//任務執行結束使用curl_easy_cleanup把內存釋放
curl_easy_cleanup(http_client->handle);
return 0;
}
int http_client_init(http_client_t*http_client, const char *url, write_cb_t *write_data, void *userp)
{
if (!url) {
return -1;
}
//初始化libcurl,設置默認參數
CURLcode return_code;
return_code= curl_global_init(CURL_GLOBAL_ALL);
if (CURLE_OK != return_code) {
printf("initlibcurl failed./n");
return -1;
}
//獲取easy handle
http_client->handle = curl_easy_init();
if (!http_client->handle) {
return -1;
}
//通過CURLOPT_URL屬性設置url
curl_easy_setopt(http_client->handle,CURLOPT_URL, url);
//注冊回調函數write_cb,回調函數將會在接收到數據的時候被調用
curl_easy_setopt(http_client->handle, CURLOPT_WRITEFUNCTION, write_data); //通過CURLOPT_USERPWD屬性來設置用戶名與密碼。參數是”user:password “的字符串
curl_easy_setopt(http_client->handle,CURLOPT_USERPWD, "karaf:karaf");
if (userp) {
//設置寫數據的變量
curl_easy_setopt(http_client->handle, CURLOPT_WRITEDATA, userp);
}
//使用curl_easy_perform執行上傳數據
curl_easy_perform(http_client->handle);
//任務執行結束使用curl_easy_cleanup把內存釋放
curl_easy_cleanup(http_client->handle);
return 0;
}
//回調函數,將接收到的數據保存到本地文件中,同時顯示在控制臺上。
static size_t write_data(void *buf, size_tsize, size_t nmemb, void *userp)
{
FILE *fp = (FILE *)userp;
size_t return_size = fwrite(buf, size, nmemb, fp);
printf("write_data: %ld, return_size: %ld/n", nmemb,return_size);
return return_size;
}
//獲取easy handle
http_client->handle = http_client_init();
if (!http_client->handle) {
return -1;
}
// 通過CURLOPT_URL屬性設置url
curl_easy_setopt(http_client->handle, CURLOPT_URL, url);
// 設置http發送的內容類型為JSON
struct curl_slist *plist = NULL;
//plist = curl_slist_append(plist,
//"Content-Type:application/json");
curl_easy_setopt(http_client->handle,CURLOPT_HTTPHEADER, plist);
// 設置要POST的JSON數據
//curl_easy_setopt(http_client->handle, CURLOPT_POSTFIELDS,szJsonData);
curl_easy_setopt(http_client->handle,CURLOPT_CUSTOMREQUEST, "DELETE");
curl_easy_setopt(http_client->handle,CURLOPT_USERPWD, "karaf:karaf");
代碼完成之后,使用gcc運行時需要帶如下參數:
gcc -o http_client http_client.ccJSON.c -lcurl –lm
編譯之后開始運行
./http_client
通過抓包可以看到http報文
注意事項:
1. -lcurl是鏈接curl庫,如果運行報如下錯誤:
mlogc.c:32:23: error: curl/curl.h: No such fileor directory
mlogc.c:1091: error: expected ‘)’ before ‘*’token
mlogc.c: In function ‘logc_init’:
則需要安裝如下依賴包:libcurl-dev, libcurl-devel
centOS上安裝依賴包:
yum install libcurl-dev libcurl-devel
2. –lm是鏈接math的庫,由于cJSON需要調用math庫,如果不添加會報如下錯誤:
3. 如果有多個方法例如:get/post/delete等用到的URL一樣,需要把如下代碼,包含URL的頭部注釋掉,否則報文發布出去。
// 設置http發送的內容類型為JSON
struct curl_slist *plist = NULL;
//plist = curl_slist_append(plist,
//"Content-Type:application/json");
curl_easy_setopt(http_client->handle,CURLOPT_HTTPHEADER, plist);
|
新聞熱點
疑難解答