当前位置: 首页 > wzjs >正文

龙岗区建设局网站珠海网站系统建设

龙岗区建设局网站,珠海网站系统建设,建筑装修装饰工程内容,python创建wordpress本文主要介绍使用libcurl multi进行curl ip_api.com的操作,ip_api.com和cjson解析,参考system专栏内容。 libcurl 的 multi 接口用于并发处理多个 HTTP 请求。它允许在单个线程中同时处理多个连接,而无需阻塞。这个多重请求接口(…

本文主要介绍使用libcurl multi进行curl ip_api.com的操作,ip_api.com和cjson解析,参考system专栏内容。

libcurlmulti 接口用于并发处理多个 HTTP 请求。它允许在单个线程中同时处理多个连接,而无需阻塞。这个多重请求接口(curl_multi_*)常用于需要发送多个 HTTP 请求的应用,如爬虫、API 聚合器等。

1. libcurl multi

1.1 基本概念

libcurlmulti 接口通过将多个 CURL 句柄组合在一个多重会话中来进行并发请求。每个句柄代表一个独立的请求,通过 curl_multi_* 函数进行管理和处理。其安装方式不做概述, libcurl - multi interface overview,该网站详细介绍了libcurl multi的api以及demo用例,可做参考。

在这里插入图片描述

1.2 常用api简介

简单介绍一下常用的api,具体的参考官网。

  • curl_multi_init():初始化一个多重会话。
CURLM *multi_handle = curl_multi_init();
  • curl_multi_add_handle():将一个 CURL 句柄添加到多重会话中。
CURL *handle = curl_easy_init();
curl_multi_add_handle(multi_handle, handle);
  • curl_multi_remove_handle():从多重会话中移除一个 CURL 句柄。
curl_multi_remove_handle(multi_handle, handle);
  • curl_multi_perform():执行并发请求。该函数会阻塞直到所有请求都完成,或者直到请求有任何进展。
int still_running;
curl_multi_perform(multi_handle, &still_running);
  • curl_multi_wait():使当前线程阻塞,直到有活动的请求需要处理。该函数通常配合 curl_multi_perform() 使用,以提高效率。
int numfds;
curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
  • curl_multi_cleanup():清理多重会话,释放资源。
curl_multi_cleanup(multi_handle);

注意事项

  • curl_multi_perform() 在执行时可能并不会立即完成所有请求,因此你需要反复调用它,直到所有请求都完成。你还可以结合 curl_multi_wait() 来优化效率,避免持续轮询。
  • 确保在多线程环境中,所有 CURL 操作都由适当的线程管理,尤其是在处理大量并发请求时。

通过这种方式,libcurl 可以高效地并行处理多个 HTTP 请求。

1.3 简单demo

下述为一个简单的使用demo,更多的demo参考官网。

#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>int main() {CURL *easy_handle1, *easy_handle2;CURLM *multi_handle;int still_running;// 初始化 multi 会话multi_handle = curl_multi_init();// 初始化两个 easy handleseasy_handle1 = curl_easy_init();easy_handle2 = curl_easy_init();// 设置 easy handle1 的 URLcurl_easy_setopt(easy_handle1, CURLOPT_URL, "http://example.com");// 设置 easy handle2 的 URLcurl_easy_setopt(easy_handle2, CURLOPT_URL, "http://example.org");// 添加两个句柄到 multi 会话curl_multi_add_handle(multi_handle, easy_handle1);curl_multi_add_handle(multi_handle, easy_handle2);// 执行请求,直到完成do {curl_multi_perform(multi_handle, &still_running);} while (still_running);// 清理curl_multi_remove_handle(multi_handle, easy_handle1);curl_multi_remove_handle(multi_handle, easy_handle2);curl_easy_cleanup(easy_handle1);curl_easy_cleanup(easy_handle2);curl_multi_cleanup(multi_handle);return 0;
}

2. 封装multi_curl接口

使用libcurl多线程方式获取IP相关信息的函数:

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>typedef struct {char *memory;size_t size;
} MemoryStruct;void mulit_get_ip_info(const char *curl_url) {CURLM *multiHandle = NULL;CURL *run_curl = NULL;MemoryStruct chunk = {0};int still_running = 0;CURLcode res;// 初始化全局环境if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {fprintf(stderr, "Curl全局初始化失败。\n");return;}// 初始化multi句柄multiHandle = curl_multi_init();if (!multiHandle) {fprintf(stderr, "Curl multi初始化失败。\n");curl_global_cleanup();return;}// 为响应数据分配内存chunk.memory = malloc(1);chunk.size = 0;if (!chunk.memory) {fprintf(stderr, "内存分配失败。\n");curl_multi_cleanup(multiHandle);curl_global_cleanup();return;}// 初始化请求并设置选项run_curl = InitCurlRequest(curl_url, &chunk);if (!run_curl) {fprintf(stderr, "初始化curl请求失败。\n");free(chunk.memory);curl_multi_cleanup(multiHandle);curl_global_cleanup();return;}// 将curl句柄添加到multi句柄res = curl_multi_add_handle(multiHandle, run_curl);if (res != CURLM_OK) {fprintf(stderr, "将句柄添加到multi句柄失败: %s\n", curl_multi_strerror(res));free(chunk.memory);curl_easy_cleanup(run_curl);curl_multi_cleanup(multiHandle);curl_global_cleanup();return;}// 执行请求do {res = curl_multi_perform(multiHandle, &still_running);if (res != CURLM_OK) {fprintf(stderr, "curl multi执行错误: %s\n", curl_multi_strerror(res));break;}} while (still_running);/******************************* 添加解析函数 ******************************/// 解析响应(此部分应该实现)// 清理并释放资源curl_multi_remove_handle(multiHandle, run_curl);curl_easy_cleanup(run_curl);curl_multi_cleanup(multiHandle);curl_global_cleanup();// 释放分配的内存if(chunk.memory) {free(chunk.memory);chunk.memory = NULL;chunk.size = 0;}
}

3.完整示例

下列为添加了解析部分的完整示例
注意: 建议将该接口放置在线程中/task中进行调用,根据调度系统选择对应的方式,下文仅为示例代码

#include <stdio.h>
#include <string.h>
#include "cJSON.h"
#include <curl/curl.h>#define CURL_IP_API     "http://ip-api.com/json/?fields=status,message,countryCode,regionName,city,lat,lon"typedef struct ip_info {char countryCode[8];char regionName[32];char city[32];double lat;double lon;
} ip_info;typedef struct {char *memory;size_t size;
} MemoryStruct;ip_info current_ip_info = {0};int parse_ip_json_str(cJSON *current_json_str){int ret = -1;cJSON *status = cJSON_GetObjectItemCaseSensitive(current_json_str, "status");if (!cJSON_IsString(status) || strcmp(status->valuestring, "success") != 0) {ret = -1;goto end;}cJSON *item;if ((item = cJSON_GetObjectItem(current_json_str, "countryCode")) && cJSON_IsString(item)) strncpy(current_ip_info.countryCode, item->valuestring, sizeof(current_ip_info.countryCode)-1);if ((item = cJSON_GetObjectItem(current_json_str, "regionName")) && cJSON_IsString(item)) strncpy(current_ip_info.regionName, item->valuestring, sizeof(current_ip_info.regionName)-1);if ((item = cJSON_GetObjectItem(current_json_str, "city")) && cJSON_IsString(item)) strncpy(current_ip_info.city, item->valuestring, sizeof(current_ip_info.city)-1);if ((item = cJSON_GetObjectItem(current_json_str, "lat")) && cJSON_IsNumber(item)) current_ip_info.lat = item->valuedouble;if ((item = cJSON_GetObjectItem(current_json_str, "lon")) && cJSON_IsNumber(item)) current_ip_info.lon = item->valuedouble;if(strlen(current_ip_info.countryCode) != 0 && strlen(current_ip_info.regionName) != 0 && strlen(current_ip_info.city) != 0 && current_ip_info.lat != 0 && current_ip_info.lon != 0) ret = 0;
end:return ret;
}void print_ip_json_parse(void) {printf("current ip info:\n");printf("countryCode ID: %s\n", current_ip_info.countryCode);printf("regionName: %s\n", current_ip_info.regionName);printf("city: %s\n", current_ip_info.city);printf("lat: %.4f\n", current_ip_info.lat);printf("lon: %.4f\n", current_ip_info.lon);printf("\n");
}size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {size_t realsize = size * nmemb;MemoryStruct *mem = (MemoryStruct *)userp;char *ptr = realloc(mem->memory, mem->size + realsize + 1);if(!ptr) return 0;mem->memory = ptr;memcpy(&(mem->memory[mem->size]), contents, realsize);mem->size += realsize;mem->memory[mem->size] = 0;return realsize;
}void mulit_get_ip_info(char *curl_url) {CURLM *multiHandle = NULL;CURL *run_curl = NULL;MemoryStruct chunk = {0};int still_running = 0;CURLcode res;// 初始化全局环境if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {fprintf(stderr, "Curl全局初始化失败。\n");return;}// 初始化multi句柄multiHandle = curl_multi_init();if (!multiHandle) {fprintf(stderr, "Curl multi初始化失败。\n");curl_global_cleanup();return;}// 为响应数据分配内存chunk.memory = malloc(1);chunk.size = 0;if (!chunk.memory) {fprintf(stderr, "内存分配失败。\n");curl_multi_cleanup(multiHandle);curl_global_cleanup();return;}// 初始化请求并设置选项run_curl = InitCurlRequest(curl_url, &chunk);if (!run_curl) {fprintf(stderr, "初始化curl请求失败。\n");free(chunk.memory);curl_multi_cleanup(multiHandle);curl_global_cleanup();return;}// 将curl句柄添加到multi句柄res = curl_multi_add_handle(multiHandle, run_curl);if (res != CURLM_OK) {fprintf(stderr, "将句柄添加到multi句柄失败: %s\n", curl_multi_strerror(res));free(chunk.memory);curl_easy_cleanup(run_curl);curl_multi_cleanup(multiHandle);curl_global_cleanup();return;}// 执行请求do {res = curl_multi_perform(multiHandle, &still_running);if (res != CURLM_OK) {fprintf(stderr, "curl multi执行错误: %s\n", curl_multi_strerror(res));break;}} while (still_running);// 解析响应cJSON *root = cJSON_Parse(chunk->memory);if(!root) goto end;if(parse_ip_json_str(root) == 0) {print_ip_json_parse();}cJSON_Delete(root);end:// 清理并释放资源curl_multi_remove_handle(multiHandle, run_curl);curl_easy_cleanup(run_curl);curl_multi_cleanup(multiHandle);curl_global_cleanup();// 释放分配的内存if(chunk.memory) {free(chunk.memory);chunk.memory = NULL;chunk.size = 0;}
}int main() {mulit_get_ip_info(CURL_IP_API);return 0;
}

改进:该示例中未对mulit_get_ip_info进行返回值判断,后续建议添加。

若有错误,麻烦指正~


文章转载自:

http://VdR8IjFY.jmtrq.cn
http://k6kpZYip.jmtrq.cn
http://wWy6jDDZ.jmtrq.cn
http://y2speBg7.jmtrq.cn
http://yt1rpX4h.jmtrq.cn
http://SGPx0Lhu.jmtrq.cn
http://t0j9Tcua.jmtrq.cn
http://paX8x5vn.jmtrq.cn
http://1GMEl62z.jmtrq.cn
http://yQSA9Wdy.jmtrq.cn
http://EObhX7Js.jmtrq.cn
http://Bj9GmGhf.jmtrq.cn
http://vxlLyi30.jmtrq.cn
http://r1KB56Z7.jmtrq.cn
http://TLMSdCId.jmtrq.cn
http://q89SfMey.jmtrq.cn
http://AlHhSZho.jmtrq.cn
http://KvRAdRVG.jmtrq.cn
http://QUBD7NzR.jmtrq.cn
http://U2s2n2Kt.jmtrq.cn
http://2kfnUQn6.jmtrq.cn
http://g2eqh7HY.jmtrq.cn
http://PF5PMOqE.jmtrq.cn
http://u1YlOZ55.jmtrq.cn
http://M03mlAxS.jmtrq.cn
http://QFMggLe0.jmtrq.cn
http://M4acHYGu.jmtrq.cn
http://BUwXeCeB.jmtrq.cn
http://y1iHDnA1.jmtrq.cn
http://GwCa1OEK.jmtrq.cn
http://www.dtcms.com/wzjs/752527.html

相关文章:

  • 网站建设-广州迅优公司卖设备用哪个网站
  • 济南外贸网站竞价托管外包服务
  • 网站通信管理部门备案交互式网站备案难吗
  • 奈曼旗华水建设工程公司网站diy电子商城网站
  • 做网站域名选择网站备案号添加超链接
  • 建网站的公司时微信云开发小程序
  • 张家口建设厅官方网站seo推广哪家服务好
  • 杨中市网站建设南京网络程序开发公司
  • 网站建设报价浩森宇特湖南省房管局官网
  • 创意家居网站建设与管理安卓app制作软件
  • 外贸商城网站制作wordpress 站内搜索代码
  • 农业网站建设营销型网站建设ppt模板下载
  • 怎么在网站投放广告百度怎样注册免费的网站
  • 找做金融的网站有哪些方面河南省住房和城乡建设厅网站首页
  • 南昌网站建设q479185700棒网站制作建设怎么收费
  • 玄武营销型网站制作厂家长安区建设局官网站站
  • 在线旅游电商网站有哪些线上线下一体化营销
  • 铜陵网站开发自己建的网站百度查找不到
  • 南宁做网站费用想做代理商去哪找项目
  • 移动网站开发技术有哪些售后好的品牌策划公司
  • 怎么样在服务器上建设网站wordpress伪静态不收录
  • 商城网站的模块设计嘉兴做微网站
  • 网站建设的竞争力长沙网站制作电话
  • 中国做网站最好的公司一张简单的网页多少钱
  • 大学html网站建设作业阿里云网站实名认证
  • 手机网站建设维护滁州seo
  • 兵团第二师建设环保局网站上海seo优化公司 kinglink
  • 免费聊天网站模板和源码农村电商网站设计与发展现状
  • 做旅行社网站网络整合营销4i原则是指
  • 地区性门户网站是什么意思编程零基础入门课程