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

Linux下MyIpAdd库的使用

一、MyIpAdd库简介

MyIpAdd库是一个纯C++库,可以用它获取我们的公网IP地址。其github地址为:https://github.com/felmur/MyIpAdd

二、下载编译MyIpAdd源码

从 https://github.com/felmur/MyIpAdd 下载MyIpAdd源码:

解压,进入源码目录,可以看到其目录结构如下:

编译:

cmake . -DCMAKE_INSTALL_PREFIX=$(pwd)/install make make install

然后源码目录下会生成MyIpAdd的库文件libMyIpAdd.so:

三、MyIpAdd的使用例子

以C++为例,编写一个使用示例。main.cpp内容如下:

#include <iostream> #include <myipadd.h> using namespace std; int main() { MyIpAdd * m = new MyIpAdd(); cout << "My public ip address is: '" << m->ip << "'" << endl; return 0; }

编译:

g++ main.cpp -o main -g -IXXX/MyIpAdd-master -LXXX/MyIpAdd-master -lMyIpAdd

运行,效果如下。可以看到本机的公网ip被成功打印出来了:

该ip和通过百度查询到的公网ip一致:

四、MyIpAdd源码里的bug

MyIpAdd源码里,myipadd.cpp的构造函数 MyIpAdd::MyIpAdd()的代码为:

MyIpAdd::MyIpAdd() { buf = static_cast<char *>(malloc(1024)); sk = socket(AF_INET, SOCK_STREAM, 0); if (sk==0) { if (DEBUG) cout << "Socket error" << endl; exit(-1); } if (DEBUG) cout << "Socket creation OK" << endl; host = gethostbyname(addr.c_str()); if (host == nullptr ) { if (DEBUG) cout << "Bad host '" << addr << "'" << endl; exit(-3); } addrin.sin_family = AF_INET; addrin.sin_port = htons(80); addrin.sin_addr.s_addr = *(reinterpret_cast<unsigned int*>(host->h_addr)); if (connect(sk, reinterpret_cast<struct sockaddr *>(&addrin), sizeof(addrin))<0){ if (DEBUG) cout << "Connection Failed" << endl; exit(-2); } if (DEBUG) cout << "Connection OK" << endl; string msg = "GET / HTTP/1.1\r\nHost: " + addr + "\r\nConnection: close\r\n\r\n"; send(sk, msg.c_str(), msg.length(), 0); ssize_t ret = 0; string html; while((ret = read( sk , buf, sizeof(buf)))>0) { *(buf+ret) = 0; html += buf; } list<string> cont; split(html,cont,'\n'); size_t r = 0; for(auto& line : cont) { if (line.length()>20) { if ((r = line.find("Current IP Address:"))!=string::npos) { string a = line.substr(r+20); a = a.substr(0,a.find("<")); if (DEBUG) cout << a << endl; ip = a; } } } close(sk); }

可以看到里面调用了exit函数:

host = gethostbyname(addr.c_str()); if (host == nullptr ) { if (DEBUG) cout << "Bad host '" << addr << "'" << endl; exit(-3); }

也就是说,当解析默认域名:checkip.dyndns.com 失败时,MyIpAdd 构造函数会直接 exit(-3),从而把整个调用MyIpAdd函数的进程退出。MyIpAdd 构造函数会把DNS/socket/connect失败当成致命错误,直接退出整个进程。

五、修复MyIpAdd源码里的退出bug

修改 MyIpAdd 源码,把MyIpAdd::MyIpAdd() 里的 exit(...) 改成“失败但不退出进程”的形式,然后重新编译 libMyIpAdd.so,就能解决调用MyIpAdd的进程退出问题。

比如修改为:

if (host == nullptr) { ip = ""; return; }

或者更完整一点:

if (host == nullptr) { if (buf) free(buf); if (sk > 0) close(sk); ip = ""; return; }

修复后,整个MyIpAdd::MyIpAdd()函数改为:

MyIpAdd::MyIpAdd() { sk = socket(AF_INET, SOCK_STREAM, 0); if (sk < 0) { if (DEBUG) cout << "Socket error" << endl; return; } if (DEBUG) cout << "Socket creation OK" << endl; host = gethostbyname(addr.c_str()); if (host == nullptr || host->h_addr == nullptr) { if (DEBUG) cout << "Bad host '" << addr << "'" << endl; close(sk); sk = -1; return; } addrin.sin_family = AF_INET; addrin.sin_port = htons(80); addrin.sin_addr.s_addr = *(reinterpret_cast<unsigned int*>(host->h_addr)); if (connect(sk, reinterpret_cast<struct sockaddr *>(&addrin), sizeof(addrin))<0){ if (DEBUG) cout << "Connection Failed" << endl; close(sk); sk = -1; return; } if (DEBUG) cout << "Connection OK" << endl; string msg = "GET / HTTP/1.1\r\nHost: " + addr + "\r\nConnection: close\r\n\r\n"; if (send(sk, msg.c_str(), msg.length(), 0) < 0) { if (DEBUG) cout << "Send Failed" << endl; close(sk); sk = -1; return; } ssize_t ret = 0; string html; char read_buf[1024]; while((ret = read(sk, read_buf, sizeof(read_buf))) > 0) { html.append(read_buf, ret); } close(sk); sk = -1; list<string> cont; split(html,cont,'\n'); size_t r = 0; for(auto& line : cont) { if (line.length()>20) { if ((r = line.find("Current IP Address:"))!=string::npos) { string a = line.substr(r+20); a = a.substr(0,a.find("<")); if (DEBUG) cout << a << endl; ip = a; } } } }

六、反思

我在某个项目中为了获取公网ip使用了MyIpAdd::MyIpAdd库。但是它的源码内部有异常退出的bug导致我的程序一直偶发挂掉。所以这给我的启发是:1.尽量用多人用的开源库,小众的开源库没什么人用往往有很多bug;2.一定要有能阅读开源库代码的能力,这样万一开源库出现问题的时候你才能修改这些bug。

http://www.jsqmd.com/news/1244209/

相关文章:

  • 羽球搭子 HarmonyOS 实战(17):比分撤销与边界校验
  • 终极解密利器AES-Killer:网络安全测试中的AES加密流量实时解密指南
  • 【超详细】二分查找(折半查找)核心知识点全解析(含多场景代码实现)
  • 2026年7月最新萧邦大连来福士维修保养服务电话 - 萧邦中国官方服务中心
  • 5个关键问题:GoFrame如何帮助企业级应用提升3倍开发效率?
  • DPPO环境扩展指南:如何将新机器人仿真环境接入训练框架
  • 2026年工商业储能系统选型指南:六款主流一体机深度对比 - 科技焦点
  • 树莓派部署BirdNET-Go常见问题解答:从硬件要求到性能优化
  • [JCMSuite] JCMSuite应用:等离子波导
  • json-swift高级技巧:函数式API带你玩转JSON数据处理
  • 2026记者采访整理录音,软件测评哪个好更适合新人使用
  • IT66318:HDMI 2.0 Retimer
  • 第四篇:《函数、指针与结构体:组织代码的核心工具》
  • Nativ:100%开源,让你在Mac本地运行AI模型,无需账户订阅!
  • 做公司PPT最烦的不是写内容,是套模板
  • B3843 [GESP202306 三级] 密码合规 题解
  • LLM输出稳定性差3倍?——从token级置信度、逻辑连贯性到领域适配度的8项硬指标深度拆解
  • 2026年经期记录小程序哪个好用?日常记录与周期预测实操经验 - 软件测评小帮手
  • 大数据hadoop的高校照明智慧监测预警系统
  • 2026 餐饮收银系统横向科普:二维火与客如云适配场景、能力差异解析
  • 2026 年文县专业的景区园林花岗岩石材订做厂家哪家专业,别让你的景区毁在石材选错上-天翔石业 - 行业推荐官[官方】--
  • AI全栈开发指南 2026 :从想法到代码只需几分钟:揭秘高效产品原型设计的AI工具栈
  • Codex工具生态与部署实践全解析
  • 崩坏星穹铁道自动化助手终极指南:如何让三月七小助手每天为你节省2小时游戏时间
  • 知网/万方/PubMed三库查重结果竟相差41.2%?揭秘AI搜索底层语义锚点偏移机制(含TensorFlow调试日志)
  • 性能/安全/异常场景提示词
  • Windows系统文件dwmghost.dll丢失找不到问题解决
  • 羽球搭子 HarmonyOS 实战(18):个人统计聚合与排行榜数据模型
  • IT66313:HDMI 2.1 Retimer
  • 数字身份的通行证:深入解析单点登录(SSO)的架构与艺术