一、curl庫的移植
前面我們已經講了,gat1400是通過http協議進行數據的交互,所以我們自然而然的想到了curl。
curl 是常用的命令行工具,用來請求 Web 服務器。cURL支持的通信協議有FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3、SMTP和RTSP(摘自百度百科)。
curl下載:https://curl.haxx.se/download.html
注:老版的curl不支持openssl.1.1加密庫,所以儘量下載高版本。
我們要的當然是curl的libcurl庫。
tar -xzvf curl-7.69.1.tar.gz
cd curl-7.69.1/
./configure --host=arm-hisiv500-linux //交叉編譯環境
make
make install
在lib/.libs/目錄下有
libcurl.so libcurl.so.4 libcurl.so.4.6.0三個動態庫(前兩個爲軟連接)以及libcurl.a一個靜態庫文件。
二、curl庫的開發
由於gat1400數據量比較大而且圖片需要進行basese64的編碼,在人流量密集的場合,如果我們還是使用一條一條數據往服務器丟會導致數據處理不過來,所以我們需要調用curl的異步機制。
看我的代碼
void *gat1400_dev_send_task(void *buf)
{
int32_t index,count;
struct list * plist;
struct le *ple;
CURL *CurlArray[CACHE_MAX_ID*4] = {NULL};
GAT1400_SEND_S *pdata[CACHE_MAX_ID*4] = {NULL};
gat1400_init_send();
plist = &gat1400_list.send_list;
while(gat1400_mod.runing && get_dev_online())
{
pthread_mutex_lock(&gat1400_list.send_mutex);
count = list_count(plist);
pthread_mutex_unlock(&gat1400_list.send_mutex);
if(count < 1)
{
usleep(100000);
continue;
}
DBG_INFO("send count:%d\n",count);
count = (count > 120 ? 120 : count);
for (index = 0; index < count; index++)
{
ple = list_head(plist);
pdata[index] = ple->data;
CurlArray[index] = curl_easy_handler(pdata[index]->http,pdata[index]->data,2000);
curl_multi_add_handle(gat1400_list.multi_handle, CurlArray[index]);
pthread_mutex_lock(&gat1400_list.send_mutex);
if(ple)
{
list_unlink(ple);
}
pthread_mutex_unlock(&gat1400_list.send_mutex);
}
lib_send_images(gat1400_list.multi_handle);
//釋放數據
for(index = 0; index < count; index++)
{
curl_multi_remove_handle(gat1400_list.multi_handle, CurlArray[index]);
curl_easy_cleanup(CurlArray[index]);
free(pdata[index]->data);
free(pdata[index]);
}
}
gat1400_uninit_send();
return NULL;
}
/*********************
封裝初始化easy句柄
***********************/
CURL * curl_easy_handler(const char *sUrl,
char *data,
unsigned int uiTimeout)
{
char http_header[512] = {0};
struct curl_slist *list = NULL;
if(NULL == sUrl || NULL == data )
{
return NULL;
}
CURL * curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, sUrl);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl,CURLOPT_POST,1); //設置問非0表示本次操作爲post
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,gat1400_null_cb); //對返回的數據進行操作的函數地址
//header
list = curl_slist_append(list, "Content-Type: application/json");
list = curl_slist_append(list, "Accept:application/json");
sprintf(http_header,GAT_HEADER_MSG,gat1400_mod.devid);
list = curl_slist_append(list, http_header);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
if (uiTimeout > 0)
{
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, uiTimeout);
}
return curl;
}
int32_t lib_send_images(CURLM * multi_handle)
{
int res = 0;
int max_fd = 50;
int return_code;
fd_set fd_read;
fd_set fd_write;
fd_set fd_except;
struct timeval tv;
tv.tv_sec = 3;
tv.tv_usec = 0;
if(NULL == multi_handle)
{
return GAT_False;
}
while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multi_handle, &res))
{
DBG_ERR("res err:%d\n",res);
}
while (res)
{
FD_ZERO(&fd_read);
FD_ZERO(&fd_write);
FD_ZERO(&fd_except);
curl_multi_fdset(multi_handle, &fd_read, &fd_write, &fd_except, &max_fd);
return_code = select(max_fd + 1, &fd_read, &fd_write, &fd_except, &tv);
if (-1 == return_code)
{
break;
}
else
{
while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multi_handle, &res))
{
DBG_ERR("res err:%d\n",res);
}
}
}
return GAT_True;
}
int32_t gat1400_init_send()
{
DBG_INFO("GAT1400 start run send task\n");
comm_set_thread_name("gat1400 send task");
gat1400_list.multi_handle = curl_multi_init();
return GAT_True;
}
int32_t gat1400_uninit_send()
{
gat1400_mod.dev_send_thread_id = 0;
curl_multi_cleanup(gat1400_list.multi_handle);
DBG_INFO("gat1400 send task exit\n");
return GAT_True;
}
代碼核心通過
curl_multi_init(); //開始
CURL * curl_easy_handler(const char *sUrl, char *data, unsigned int uiTimeout);
curl_multi_add_handle(CURLM *multi_handle, CURL *curl_handle);
curl_multi_perform(CURLM *multi_handle, int *running_handles);
curl_multi_remove_handle(CURLM *multi_handle, CURL *curl_handle);
curl_easy_cleanup(CURL *curl);
curl_multi_cleanup(CURLM *multi_handle); //結束
流程對數據進行上傳處理。
我在800wIPC相機上測試,在吃掉80M內存情況下,1s進行30張人臉上傳數據是沒有壓力的。
有錯誤請留言,謝謝。
bob 2020-04-07