首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从IP_ADDRESS_STRING ()获得一个GetAdaptersAddresses?

从IP_ADDRESS_STRING ()获得一个GetAdaptersAddresses?
EN

Stack Overflow用户
提问于 2010-10-21 16:00:48
回答 3查看 11.5K关注 0票数 7

GetAdaptersAddresses()将获得IP_ADAPTER_UNICAST_ADDRESS格式的地址,定义为:

代码语言:javascript
复制
typedef struct _IP_ADAPTER_UNICAST_ADDRESS {
  union {
    struct {
      ULONG Length;
      DWORD Flags;
    } ;
  } ;
  struct _IP_ADAPTER_UNICAST_ADDRESS *Next;
  SOCKET_ADDRESS                     Address;
  IP_PREFIX_ORIGIN                   PrefixOrigin;
  IP_SUFFIX_ORIGIN                   SuffixOrigin;
  IP_DAD_STATE                       DadState;
  ULONG                              ValidLifetime;
  ULONG                              PreferredLifetime;
  ULONG                              LeaseLifetime;
  UINT8                              OnLinkPrefixLength;
} IP_ADAPTER_UNICAST_ADDRESS, *PIP_ADAPTER_UNICAST_ADDRESS;

唯一似乎暗示人类可读的IP地址字符串的字段是地址,它是一个定义为:

代码语言:javascript
复制
typedef struct _SOCKET_ADDRESS {
  LPSOCKADDR lpSockaddr;
  INT        iSockaddrLength;
} SOCKET_ADDRESS, *PSOCKET_ADDRESS;

它又使用另一个结构,SOCKADDR,定义为:

对不起,这是一个复杂的方式在这里发布,因为它的变化取决于IPv4与IPv6和Windows版本.因此,这里有一个指向定义的链接:

http://msdn.microsoft.com/en-us/library/ms740496%28v=VS.85%29.aspx

如果您还没有像我这样头晕目眩,然后继续进行这个迷宫式的定义,那么您可能会注意到,检索IP地址的好的旧虚线样式是一场噩梦,因为使用GetAdaptersInfo()过去要容易得多。

我的问题是:是否有真正的IP帮助函数可以将IP_ADAPTER_UNICAST_ADDRESS转换为IPv4虚线字符串(或IPv6字符串)?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-10-21 16:06:21

您可以使用GetIpAddrTable -- 返回数据结构包含一个DWORD dwAddr,即IPv4地址。第一个链接上的示例代码应该显示您想要的内容。简短的节选,让你明白我的意思:

代码语言:javascript
复制
if ( (dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 )) != NO_ERROR ) { 
    printf("GetIpAddrTable failed with error %d\n", dwRetVal);
    if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),       // Default language
                      (LPTSTR) & lpMsgBuf, 0, NULL)) {
        printf("\tError: %s", lpMsgBuf);
        LocalFree(lpMsgBuf);
    }
    exit(1);
}

printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
    printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex);
    IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
    printf("\tIP Address[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );

IP_ADAPTER_UNICAST_ADDRESS包含Address中的SOCKET_ADDRESS,而后者又包含lpSockAddr中的LPSOCKADDR --您可以使用WSAAddressToString将其转换为ipv4字符串表单。

票数 7
EN

Stack Overflow用户

发布于 2012-11-26 20:07:58

查看一下SOCKADDR的文档。这就引出了存储的文档,它是IPv4和IPv6的辅助结构。

引用sockaddr文档:

使用sockaddr的Winsock函数不会严格解释为指向sockaddr结构的指针。这种结构在不同的称谓族中被不同的解释。

对于ipv4,可以将套接字指针转换为sockaddr_in指针,然后从那里访问IPv4地址信息。然后,您可以使用您最喜欢的字符串生成器来生成一个虚线四边形格式的字符串。

代码语言:javascript
复制
sockaddr_in* address = (sockaddr_in*) temp->Address.lpSockaddr;
uint32_t ipv4 = address->sin_addr.S_un.S_addr;
// First octet:  address->sin_addr.S_un.S_un_b.s_b1
// Second octet: address->sin_addr.S_un.S_un_b.s_b2
// Third octet:  address->sin_addr.S_un.S_un_b.s_b3
// Fourth octet: address->sin_addr.S_un.S_un_b.s_b4

我可以想象,如果给出了结构定义(下面复制),您也可以以类似的方式为ipv6转换地址。

代码语言:javascript
复制
struct sockaddr {
        ushort  sa_family;
        char    sa_data[14];
};

struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
};

struct sockaddr_in6 {
        short   sin6_family;
        u_short sin6_port;
        u_long  sin6_flowinfo;
        struct  in6_addr sin6_addr;
        u_long  sin6_scope_id;
};
票数 5
EN

Stack Overflow用户

发布于 2018-03-20 14:57:06

您可以简单地将_SOCKET_ADDRESS.lpSockaddr_SOCKET_ADDRESS.iSockaddrLength作为lpsaAddressdwAddressLength参数传递给WSAAddressToString函数。WSAAddressToString会为你做必要的转换,不需要深入挖掘。

代码语言:javascript
复制
function SOCKET_ADDRESS_ToString(const Addr: SOCKET_ADDRESS): String;
var
  Len: DWORD;
begin
  if (Addr.lpSockaddr = nil) or (Addr.iSockaddrLength <= 0) then
  begin
    Result := '';
    Exit;
  end;
  Len := 0;
  WSAAddressToString(Addr.lpSockaddr, Addr.iSockaddrLength, nil, nil, Len);
  SetLength(Result, Len);
  if WSAAddressToString(Addr.lpSockaddr, Addr.iSockaddrLength, nil, PChar(Result), Len) = 0 then
    SetLength(Result, Len - 1)
  else
    Result := '';
end;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3989446

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档