【问题标题】:How do I get the IPv4 address of my server application?如何获取服务器应用程序的 IPv4 地址?
【发布时间】:2021-12-22 19:36:47
【问题描述】:

即使在筛选了许多相关帖子之后,我似乎也找不到合适的答案。我有一个 winsock2 应用程序(用于服务器设置的代码从 the microsoft documentation 适应我的需要),我只想在绑定后显示服务器 IPv4 地址。 这是我到目前为止的代码(在绑定到 ListenSocket 之后放置):

    char ipv4[80];
    sockaddr_in inaddr;
    int len = sizeof(inaddr);
    int error = getsockname(m_ListenSocket, (sockaddr*)&inaddr, &len);
    const char* p = inet_ntop(AF_INET, &inaddr.sin_addr, ipv4, 80);
    std::cout << "Server address: " << ipv4 << std::endl;

但是,这将返回“0.0.0.0”。如果我将inet_ntopstruct addrinfo* result 一起使用(参见上面的链接文档),我会得到一个以“2.xxx.xxx.xxx”开头的IP,而我知道我的本地地址是“192.168.1.18”。在上面的代码中,error 为 0,inet_ntop 的结果不是NULL。 如何让实际 IP 地址显示出来?

【问题讨论】:

  • 如果你已经将套接字绑定到 0.0.0.0 那么它就没有一个 ip 地址
  • @AlanBirtles 所以这意味着,我必须使用gethostname()gethostbyname() 来获取实际的IP 地址?至少我在谷歌搜索后假设...
  • 这当然是一种方式但是比较绕,可以直接获取信息stackoverflow.com/questions/37902643/…
  • 天哪,非常感谢,我会调查一下。我的 Google-Fu 今天真的让我失望了……
  • @RolandDeschain 请注意,该方法将为您提供系统上的每个 IP,而不是套接字实际侦听的 IP。它可能无法侦听所有可能的 IP,例如,如果某些 IP 被独占使用、已配置但已禁用等。当绑定到 0.0.0.0 时,只要至少有一个 IP 接口,绑定/侦听就会成功能够听。但是,没有 API 可以准确地确定套接字实际监听的 IP。

标签: c++ winsock2


【解决方案1】:

来自Microsoft的示例代码

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;
// Link with Iphlpapi.lib
#pragma comment(lib,"IPHLPAPI.lib")
#pragma comment(lib,"Ws2_32.lib")

const unsigned int WORKING_BUFFER_SIZE = 15 * 1024;

void displayAddress(const SOCKET_ADDRESS &Address)
{
//  cout << "\n  Length of sockaddr: " << Address.iSockaddrLength;
    if (Address.lpSockaddr->sa_family == AF_INET)
    {
        sockaddr_in *si = (sockaddr_in *)(Address.lpSockaddr);
        char a[INET_ADDRSTRLEN] = {};
        if (inet_ntop(AF_INET, &(si->sin_addr), a, sizeof(a)))
            cout << "\n   IPv4 address: " << a;
    }
    else if (Address.lpSockaddr->sa_family == AF_INET6)
    {
        sockaddr_in6 *si = (sockaddr_in6 *)(Address.lpSockaddr);
        char a[INET6_ADDRSTRLEN] = {};
        if (inet_ntop(AF_INET6, &(si->sin6_addr), a, sizeof(a)))
            cout << "\n   IPv6 address: " << a;
    }
}

int main(){
    DWORD dwSize = 0;
    DWORD dwRetVal = 0;
    ULONG outBufLen = WORKING_BUFFER_SIZE;

    ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
    PIP_ADAPTER_ADDRESSES pAddresses = NULL;
    PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;

    pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(WORKING_BUFFER_SIZE);

    dwRetVal = GetAdaptersAddresses(AF_INET, flags, NULL, pAddresses, &outBufLen);

    if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
        free(pAddresses);
        cout << "Buffer error!" << endl;
        return -1;
    }

    pCurrAddresses = pAddresses;
    while (pCurrAddresses) {

        for (PIP_ADAPTER_UNICAST_ADDRESS pu = pCurrAddresses->FirstUnicastAddress; pu != NULL; pu = pu->Next)
            displayAddress(pu->Address);

        pCurrAddresses = pCurrAddresses->Next;
    }

    free(pAddresses);

    cout << endl;

    return 0;
}

【讨论】:

  • 如果GetAdaptersAddresses() 返回ERROR_BUFFER_OVERFLOW,您只需将pAddresses 重新分配给返回的字节大小,然后重试。循环重复此操作,直到不再返回ERROR_BUFFER_OVERFLOW,然后根据最终返回值做出反应。在大多数系统上,IP 数据不太可能超过 15K,但可能会。
猜你喜欢
  • 2023-03-09
  • 2014-05-12
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
  • 2012-10-13
  • 2015-09-02
  • 2010-11-07
相关资源
最近更新 更多