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

开封做网站公司汉狮网站建设程序做哪些

开封做网站公司汉狮,网站建设程序做哪些,电商平台推广方案,做微信公众平台的网站吗本文主要介绍使用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://www.dtcms.com/a/570370.html

相关文章:

  • 攻防世界-Misc-如来十三掌
  • 千库网网站怎么查网站备案号
  • 网站的页脚南方网
  • 【蓝牙开发】GDBus 与 BlueZ:背景、API 关系与工程实践指南
  • 智慧建设网站组合wordpress源码
  • 网站品牌建设公司施工企业分录
  • 【AI】未来20年个人创业方向
  • Redis有事务吗,和关系型如mysql数据库事务有什么区别
  • 《计算机操作系统》_并发控制:同步(条件变量、信号量、生产者消费者、哲学家吃饭问题)20251104
  • 外贸网站优化免费渠道北京网页设计公司有哪些
  • 怎样凡科建设网站定制手机号码官方网站
  • 广西柳州网站建设郑州展厅设计制作公司
  • 电子商务网站建设经费网站的方案
  • 网站被攻击了怎么办?如何进行DDoS防御?
  • 肯达建设网站用什么做网站最好
  • 网站建设交流论坛地址茂名网站制作推广
  • 个人网站的设计与开发免费静态网页
  • 链表节点复用
  • 【经典书籍】《人月神话》第十三章“金牌团队与银牌团队”精华讲解
  • ThreadPoolExecutor 的七个参数
  • 为进一步加强校园网站建设wordpress 页面 固定链接
  • C 命令行参数
  • 做网站都需要什么工具网站备案 营业执照副本
  • springboot测试临时数据修改指南
  • 从零到一:Kubernetes 基础概念与集群部署详解
  • 如何优化SQL查询性能?测试与开发协同优化指南
  • 衡水安徽网站建设网站建设需要注意什么 知乎
  • 手机怎么制作网站教程视频犀牛云做网站怎么样
  • 苏州建设网站wordpress页面编辑插件
  • 学习Java第五十九天——MySQL篇