前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >客户端面试题:如何获取公网IP?

客户端面试题:如何获取公网IP?

作者头像
程序员的园
发布2025-02-12 14:22:46
发布2025-02-12 14:22:46
10500
代码可运行
举报
运行总次数:0
代码可运行

本文是读者朋友的面试真题,客户端如何获取本地的公网IP。

在当今的网络时代,许多程序和服务都依赖于公网IP——用于标识设备在互联网位置的全球唯一标识符。例如,Web服务器、FTP服务器或游戏服务器等需要借助公网IP来确保用户可以访问。故此准确获取公网IP地址显得尤为重要。

公网IP

日常接触到的形如192.168.1.100等IP地址,都是私网IP,它们只在局域网内有效,不能在互联网上被识别。而公网IP(Public IP Address)是由互联网服务提供商(ISP)分配给用户的地址,它用于在全球互联网上标识一个设备。公网IP与私网IP之间通过NAT(网络地址转换)实现转换,使得多台设备可以共享一个公网IP。

公网IP有着至关重要的作用:

  • 识别设备身份:公网IP使得互联网上的其他设备能够准确识别你的设备位置,从而建立连接。
  • 远程访问:对于服务器或其他网络服务,公网IP是外部用户访问的关键,帮助你将服务暴露给外部网络。
  • 安全性控制:网络防火墙、路由器等设备可以根据公网IP来进行访问控制。

可是该如何获取公网地址呢?

IP查询服务

为了方便用户查询公网IP,许多网站提供了公网IP查询服务。这些网站通常提供一个简单的接口,用户只需访问这些网站,即可获取到自己的公网IP。常见的IP查询服务网址如下:

  • http://api.ipify.org
  • http://icanhazip.com
  • http://checkip.amazonaws.com
  • http://ipinfo.io/ip
  • http://myexternalip.com/raw
  • http://www.trackip.net/ip
  • http://ipecho.net/plain
  • http://myip.dnsomatic.com
  • http://www.ip-adress.com/

在浏览器内请求如上的任意一个网址,即可获取公网IP地址。

C++实现

虽然如上的IP查询服务网站可以方便地获取到公网IP,但开发者终究还是需要落实到代码上,代码实现时依然可以借助如上的IP查询服务网站,实现的思路如下:

  • 通过HTTP请求获取公网IP,解析响应消息获得公网IP;
  • 为避免IP查询服务网站可能存在的异常情况,将查询多个网站,直到请求成功或请求完所有的的IP查询服务网址为止。

准备工作

在实现网络请求时,借助C++的libcurl库,可通过vcpkg工具下载该库,vcpkg的使用见之前的文章——vcpkg 如何改变开发流程? ;libcurl的使用见之前的文章——无论多么复杂的网络请求,只需要这7步就够了

代码实现

以下是一个C++类的实现,它会依次尝试多个公共API来获取本机的公网IP。如果第一个API请求失败,它会继续尝试下一个,直到找到一个有效的IP或者所有都失请求都失败为止。

代码语言:javascript
代码运行次数:0
复制
#include <iostream>
#include <string>
#include <curl/curl.h>
#include <vector>

class PublicIPFetcher {
public:
    // 构造函数初始化API列表
    PublicIPFetcher() {
        // 这里列出了10个公网IP查询API(可根据需要增加/修改)
        apis = {
            "http://api.ipify.org";
            "http://icanhazip.com";
            "http://checkip.amazonaws.com";
            "http://ipinfo.io/ip";
            "http://myexternalip.com/raw";
            "http://www.trackip.net/ip";
            "http://ipecho.net/plain";
            "http://myip.dnsomatic.com";
            "http://www.ip-adress.com/";
        };
    }

    // 获取公网IP,按顺序依次请求API
    bool getPublicIP(std::string& ip) {
        CURL *curl;
        CURLcode res;

        curl_global_init(CURL_GLOBAL_DEFAULT);
        curl = curl_easy_init();

        if (!curl) {
            std::cerr << "Curl initialization failed!" << std::endl;
            curl_global_cleanup();
            returnfalse;
        }

        for (constauto& api : apis) {
            ip.clear(); // 清空之前的IP
            curl_easy_setopt(curl, CURLOPT_URL, api.c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ip);

            res = curl_easy_perform(curl);
            if (res == CURLE_OK && !ip.empty()) {
                std::cout << "Public IP fetched from: " << api << std::endl;
                curl_easy_cleanup(curl);
                curl_global_cleanup();
                returntrue;
            }
        }

        // 如果所有API都失败
        curl_easy_cleanup(curl);
        curl_global_cleanup();
        returnfalse;
    }

private:
    // 保存API列表
    std::vector<std::string> apis;

    // 写入回调函数,将获取的数据保存到ip变量中
    static size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp) {
        size_t totalSize = size * nmemb;
        ((std::string*)userp)->append((char*)contents, totalSize);
        return totalSize;
    }
};

int main() {
    PublicIPFetcher fetcher;
    std::string ip;

    if (fetcher.getPublicIP(ip)) {
        std::cout << "Public IP: " << ip << std::endl;
    } else {
        std::cout << "Failed to retrieve public IP." << std::endl;
    }

    return0;
}

如上的代码,getPublicIP函数返回false,说明没有成功获取公网IP;返回true,则说明成功获取了公网IP,并且IP地址会保存在ip变量中。

5. 结论

通过C++代码获取公网IP的需求在许多网络应用中是常见的,尤其是在需要与外部网络进行交互时。通过向多个IP查询服务网站发送请求,可以提高获取公网IP的可靠性。本文提供了一个可以动态尝试多个API的C++类来实现这一功能。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-02-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的园 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 公网IP
  • IP查询服务
  • C++实现
    • 准备工作
    • 代码实现
  • 5. 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档