C++ 使用 Boost.Asio 获取本地 IP 地址

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2674314/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:18:42  来源:igfitidea点击:

Get Local IP-Address using Boost.Asio

c++ip-addressboost-asio

提问by MOnsDaR

I'm currently searching for a portable way of getting the local IP-addresses. Because I'm using Boost anyway I thought it would be a good idea to use Boost.Asio for this task.

我目前正在寻找一种获取本地 IP 地址的便携式方法。因为无论如何我都在使用 Boost,所以我认为使用 Boost.Asio 来完成这项任务是个好主意。

There are several examples on the net which should do the trick. Examples:

网上有几个例子应该可以解决问题。例子:

Official Boost.Asio Documentation

官方 Boost.Asio 文档

Some Asian Page

一些亚洲页面

I tried both codes with just slight modifications. The Code on Boost.Doc was changed to not resolve "www.boost.org" but "localhost" or my hostname instead. For getting the hostname I used boost::asio::ip::host_name() or typed it directly as a string.

我只稍作修改就尝试了这两个代码。Boost.Doc 上的代码已更改为不解析“www.boost.org”,而是解析“localhost”或我的主机名。为了获取主机名,我使用了 boost::asio::ip::host_name() 或直接将其作为字符串键入。

Additionally I wrote my own code which was a merge of the above examples and my (little) knowledge I gathered from the Boost Documentation and other examples.

此外,我编写了自己的代码,它融合了上述示例和我从 Boost 文档和其他示例中收集的(一点)知识。

All the sources worked, but they did just return the following IP:
127.0.1.1 (That's not a typo, its .1.1 at the end)
I run and compiled the code on Ubuntu 9.10 with GCC 4.4.1

所有源代码都有效,但它们确实返回了以下 IP:
127.0.1.1(这不是打字错误,最后是 .1.1)
我在 Ubuntu 9.10 和 GCC 4.4.1 上运行并编译了代码

A colleague tried the same code on his machine and got
127.0.0.2 (Not a typo too...)
He compiled and run on Suse 11.0 with GCC 4.4.1 (I'm not 100% sure)

一位同事在他的机器上尝试了相同的代码并得到了
127.0.0.2(也不是错别字......)
他使用 GCC 4.4.1 在 Suse 11.0 上编译并运行(我不是 100% 确定)

I don't know if it is possible to change the localhost (127.0.0.1), but I know that neither me or my colleague did it. ifconfig says loopback uses 127.0.0.1. ifconfig also finds the public IP I am searching for (141.200.182.30 in my case, subnet is 255.255.0.0)

我不知道是否可以更改 localhost (127.0.0.1),但我知道我和我的同事都没有这样做。ifconfig 说环回使用 127.0.0.1。ifconfig 还会找到我正在搜索的公共 IP(在我的例子中是 141.200.182.30,子网是 255.255.0.0)

So is this a Linux-issue and the code is not as portable as I thought? Do I have to change something else or is Boost.Asio not working as a solution for my problem at all?

那么这是一个 Linux 问题吗,代码不像我想象的那么可移植?我是否必须更改其他内容,还是 Boost.Asio 根本无法解决我的问题?

I know there are much questions about similar topics on Stackoverflow and other pages, but I cannot find information which is useful in my case. If you got useful links, it would be nice if you could point me to it.

我知道在 Stackoverflow 和其他页面上有很多关于类似主题的问题,但我找不到对我有用的信息。如果你有有用的链接,如果你能指点我就太好了。

PS: Here is the modified code I used from Boost.Doc:

PS:这是我从 Boost.Doc 使用的修改后的代码:

#include <boost/asio.hpp>
using boost::asio::ip::tcp;    

boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(boost::asio::ip::host_name(), "");
tcp::resolver::iterator iter = resolver.resolve(query);
tcp::resolver::iterator end; // End marker.
while (iter != end)
{
    tcp::endpoint ep = *iter++;
    std::cout << ep << std::endl;
}

回答by SJL

Here's a trick I learned from python network programming (google) to figure out my machine's ip address. This only works if you have an internet connection and can connect to google.com and does give me my home machine's 192.168.x.x private address.

这是我从 python 网络编程(谷歌)中学到的一个技巧来找出我机器的 ip 地址。这只适用于您有互联网连接并且可以连接到 google.com 并且确实给了我我的家用机器的 192.168.xx 私人地址。

try {
    boost::asio::io_service netService;
    udp::resolver   resolver(netService);
    udp::resolver::query query(udp::v4(), "google.com", "");
    udp::resolver::iterator endpoints = resolver.resolve(query);
    udp::endpoint ep = *endpoints;
    udp::socket socket(netService);
    socket.connect(ep);
    boost::asio::ip::address addr = socket.local_endpoint().address();
    std::cout << "My IP according to google is: " << addr.to_string() << std::endl;
 } catch (std::exception& e){
    std::cerr << "Could not deal with socket. Exception: " << e.what() << std::endl;

 }

回答by moodboom

You can find "your" address with the code you posted. BUT... it gets complicated. There may be multiple NICs, there may be LAN and WAN addresses, wired and wireless, loopback... On my desktop i had one NIC but two ips here from two diff DHCP servers on my lan...

您可以使用您发布的代码找到“您的”地址。但是……事情变得复杂了。可能有多个网卡,可能有 LAN 和 WAN 地址,有线和无线,环回...在我的桌面上,我有一个网卡,但这里有两个来自我局域网上两个不同 DHCP 服务器的 ips...

I found it was better to let the user provide the IP to bind to as a command line parameter. And yes, that's a portable solution! :-)

我发现让用户提供要绑定的 IP 作为命令行参数会更好。是的,这是一个便携式解决方案!:-)

回答by user361756

If you edit your /etc/hosts file (this is *nix only, might work for windows too... I'm not sure) you can correct this issue.

如果你编辑你的 /etc/hosts 文件(这只是 *nix,可能也适用于 Windows...我不确定)你可以纠正这个问题。

Inside the hosts file you'll find something like: (this is Ubuntu, note the 1.1)

在 hosts 文件中,您会发现如下内容:(这是 Ubuntu,请注意 1.1)

127.0.0.1 localhost
127.0.1.1 yourPcName.yourNetwork.tld

127.0.0.1 本地主机
127.0.1.1 yourPcName.yourNetwork.tld

if you change this file to

如果您将此文件更改为

127.0.0.1 localhost
127.0.1.1 yourPcName.yourNetwork.tld
your.real.ip.here yourPcName

127.0.0.1 本地主机
127.0.1.1 yourPcName.yourNetwork.tld
your.real.ip.here yourPcName

then the hostname should resolve properly.

那么主机名应该正确解析。

One method of testing proper resolution is with the "hostname -i" command which should print your ip address incorrectly before you change hosts, and then correctly afterwards.

测试正确解析的一种方法是使用“hostname -i”命令,该命令应该在您更改主机之前错误地打印您的 IP 地址,然后正确地打印出来。

Of course this is terrible solution for dynamic IPs... eh.

当然,这是动态 IP 的糟糕解决方案......呃。