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

curl获取ip定位信息 --- system(一)

本文使用curl获取ip地理位置的json格式,并通过cjson进行解析,使用curl的三种方式进行请求:

  • 命令行system()将curl后的内容拷贝到文件中,后进行解析

  • 使用libcurl请求

  • 使用libcurl multi 异步方式请求

1.获取ip地理位置的api

常用的获取ip地理位置的api:

  • ip-api.com 接口,具体使用方式查看官网
http://ip-api.com/json/{query}
  • whois.pconline.com.cn 接口
http://whois.pconline.com.cn/ipJson.jsp

本文使用ip_api.com接口,可在网页上进行demo测试,网址如下:

https://ip-api.com/docs/api:json

在这里插入图片描述

可以在returned date勾选需要返回的值

在这里插入图片描述

例如,需获取当前ip的countryCode,regionName,city,lat,lon,则勾线相应的选项

在这里插入图片描述

点击demo按键,则会跳转到测试回复这里,则会显示当前回复的数据内容

在这里插入图片描述

2. 使用cjson进行解析

  • cJson:一个基于 C 语言的 Json 库,它是一个开源项目,github 下载地址:cjosn github 地址
  • cJson库组成:主要的文件有两个,一个 cJSON.c 一个 cJSON.h。使用时,将头文件 include 进去即可

本文不对cjson进行详细说明

首先将json串进行压缩转义,可使用的网址为:压缩转义json网页,将上述返回值转义为字符串,方便测试,例如:

{\"status\":\"success\",\"country\":\"Canada\",\"countryCode\":\"CA\",\"regionName\":\"Quebec\",\"city\":\"Montreal\",\"lat\":45.6026,\"lon\":-73.5167}

根据ip_api的返回值json,可进行相关解析,解析如下:

#include <stdio.h>
#include <string.h>
#include "cJSON.h"typedef struct ip_info {char countryCode[8];char regionName[32];char city[32];double lat;double lon;
} ip_info;ip_info current_ip_info = {0};int parse_ip_json_str(const char *current_json_str){int ret = -1;cJSON *tmp_json = cJSON_Parse(current_json_str);if (!tmp_json ) {const char *error_ptr = cJSON_GetErrorPtr();if (error_ptr) fprintf(stderr, "JSON解析错误: %s\n", error_ptr);return -1;}cJSON *status = cJSON_GetObjectItemCaseSensitive(tmp_json , "status");if (!cJSON_IsString(status) || strcmp(status->valuestring, "success") != 0) {ret = -1;goto end;}cJSON *item;if ((item = cJSON_GetObjectItem(tmp_json , "countryCode")) && cJSON_IsString(item)) strncpy(current_ip_info.countryCode, item->valuestring, sizeof(current_ip_info.countryCode)-1);if ((item = cJSON_GetObjectItem(tmp_json , "regionName")) && cJSON_IsString(item)) strncpy(current_ip_info.regionName, item->valuestring, sizeof(current_ip_info.regionName)-1);if ((item = cJSON_GetObjectItem(tmp_json , "city")) && cJSON_IsString(item)) strncpy(current_ip_info.city, item->valuestring, sizeof(current_ip_info.city)-1);if ((item = cJSON_GetObjectItem(tmp_json , "lat")) && cJSON_IsNumber(item)) current_ip_info.lat = item->valuedouble;if ((item = cJSON_GetObjectItem(tmp_json , "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:cJSON_Delete(tmp_json);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");
}int main() {const char json_str[] = ""{\"status\":\"success\",\"country\":\"Canada\",\"countryCode\":\"CA\",\"regionName\":\"Quebec\",\"city\":\"Montreal\",\"lat\":45.6026,\"lon\":-73.5167};if(parse_ip_json_str(json_str) == 0) {print_ip_json_parse();}
}

则打印结果为:

在这里插入图片描述

3. 使用curl获取api返回值

3.1 使用system指令直接获取

使用system(curl ....) 是通过调用系统的命令行来运行 curl 命令。这意味着它会启动一个外部进程来执行 curl,并在终端或命令行环境中运行该命令。

缺点

  • 性能开销:每次调用 system(curl) 都需要启动一个新的外部进程,这会增加系统开销,影响性能;
  • 且若无系统调度,则会阻塞主线程的运行;
  • 依赖于系统的 curl 命令:你必须依赖外部 curl 工具,无法灵活控制;
  • 输出不方便处理:调用 system(curl) 会将结果输出到标准输出,处理结果需要额外的工作;
  • 安全性:如果拼接命令字符串时不小心,可能会导致安全漏洞,尤其是在传递不受信任的输入时;

则该方式适合测试时使用,或者调用次数及性能要求不高的场景需求,不推荐在正式代码中使用,本文采用静默且将输出保存到文件中,封装的函数如下;

void execute_curl(const char *url, const char *output_file) {char command[256] = {0};if (output_file) {snprintf(command, sizeof(command), "curl -s -o '%s' '%s'", output_file, url);} else {snprintf(command, sizeof(command), "curl -s '%s'", url);}system(command);
}

则使用其进行curl请求

#define TEMP_FILE_PATH "/tmp/tmp_file.json"
#define CURL_IP_API     "http://ip-api.com/json/?fields=status,message,countryCode,regionName,city,lat,lon"execute_curl(CURL_IP_API, TEMP_FILE_PATH);

使用cat指令查看,确定是保存成功的,如下

在这里插入图片描述

之后就可以将其从文件中读出,删除tmp文件,解析json数据,下面为将其从文件读出,并返回json数据的代码:

cJSON *parse_json_file(const char *filename) {FILE *fp = fopen(filename, "rb");  // 以二进制模式打开确保ftell正确if (!fp) return NULL;// 获取文件大小fseek(fp, 0, SEEK_END);long file_size = ftell(fp);fseek(fp, 0, SEEK_SET);// 处理空文件情况if (file_size <= 0) {fclose(fp);return NULL;}// 动态分配缓冲区char *buffer = (char*)malloc(file_size + 1);if (!buffer) {fclose(fp);return NULL;}// 读取文件内容size_t bytes_read = fread(buffer, 1, file_size, fp);fclose(fp);if (bytes_read != (size_t)file_size) {free(buffer);return NULL;}// 添加字符串终止符buffer[bytes_read] = '\0';// 解析JSONcJSON *json = cJSON_Parse(buffer);free(buffer);  // 释放原始缓冲区return json;
}

可根据需求添加是否要删除临时文件

unlink(TEMP_FILE_PATH);

则将其整合起来的代码如下:

#include <stdio.h>
#include <string.h>
#include "cJSON.h"
#include <<unistd.h>#define TEMP_FILE_PATH "/tmp/tmp_file.json"
#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;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");
}cJSON *parse_json_file(const char *filename) {FILE *fp = fopen(filename, "rb");  // 以二进制模式打开确保ftell正确if (!fp) return NULL;// 获取文件大小fseek(fp, 0, SEEK_END);long file_size = ftell(fp);fseek(fp, 0, SEEK_SET);// 处理空文件情况if (file_size <= 0) {fclose(fp);return NULL;}// 动态分配缓冲区char *buffer = (char*)malloc(file_size + 1);if (!buffer) {fclose(fp);return NULL;}// 读取文件内容size_t bytes_read = fread(buffer, 1, file_size, fp);fclose(fp);if (bytes_read != (size_t)file_size) {free(buffer);return NULL;}// 添加字符串终止符buffer[bytes_read] = '\0';// 解析JSONcJSON *json = cJSON_Parse(buffer);free(buffer);  // 释放原始缓冲区return json;
}int main() {execute_curl(CURL_IP_API, TEMP_FILE_PATH);cJSON *root = parse_json_file(TEMP_FILE_PATH);if (!root) {printf("parse_json_file error\r\n");unlink(TEMP_FILE_PATH)return -1;}if(parse_ip_json_str(root) == 0) {print_ip_json_parse();}cJSON_Delete(root);unlink(TEMP_FILE_PATH);return 0;
}

使用libcurl请求和使用libcurl multi 异步方式请看下篇,如有错误,请指正,谢谢~

相关文章:

  • Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
  • 基于 BGE 模型与 Flask 的智能问答系统开发实践
  • 大模型与 NLP、Transformer 架构
  • 动力电池点焊机:驱动电池焊接高效与可靠的核心力量|比斯特自动化
  • 深入理解Java中的this关键字:核心概念与实践应用
  • XXTEA,XTEA与TEA
  • html+css+js趣味小游戏~Cookie Clicker放置休闲(附源码)
  • 探索 Java 垃圾收集:对象存活判定、回收流程与内存策略
  • 【大厂机试题多种解法笔记】小明减肥
  • 【推荐算法】DeepFM:特征交叉建模的革命性架构
  • python报错No module named ‘tensorflow.keras‘
  • 【CF】Day77——Codeforces Round 877 (Div. 2) BCD (构造场)
  • 智绅科技 —— 智慧养老 + 数字健康,构筑银发时代安全防护网
  • TDengine 替换 Hadoop,彻底解决数据丢失问题 !
  • 【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
  • Redis哨兵模式
  • 【SSM】MyBatisPlus笔记:快速上手MyBatisPlus
  • CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
  • 沙市区举办资本市场赋能培训会 点赋科技分享智能消费新实践
  • 大语言模型提示词(LLM Prompt)工程系统性学习指南:从理论基础到实战应用的完整体系
  • html5模板免费下载/seo网络优化培训
  • 做网站的公司叫什么名字/成都网站优化平台
  • 青岛企业网站模板建站/太原关键词优化软件
  • 深圳公司网站推广/seo网络优化
  • 本人找做钢筋笼的活网站/网络营销顾问招聘
  • 专业微信网站建设多少钱/长春百度seo排名