C++ 如何从'sockaddr_storage'实例检索IP和端口?

C++ 如何从'sockaddr_storage'实例检索IP和端口?,c++,c,sockets,networking,winsock,C++,C,Sockets,Networking,Winsock,如何使用getnameinfo()()从sockaddr\u存储实例检索IP和端口 当我使用inet\u ntop时,它工作正常,但当我用getnameinfo函数替换它时,Windows返回了一个错误: 代码10047:使用了与请求的协议不兼容的地址 我查看了您的问题,并能够重现您的错误 可复制示例: #define WIN32_LEAN_AND_MEAN #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <cstdint> #in

如何使用
getnameinfo()
()从
sockaddr\u存储
实例检索IP和端口

当我使用
inet\u ntop
时,它工作正常,但当我用
getnameinfo
函数替换它时,Windows返回了一个错误:

代码10047:使用了与请求的协议不兼容的地址


我查看了您的问题,并能够重现您的错误

可复制示例:

#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>

int main(int, char **) {

  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;
  WSAStartup(wVersionRequested, &wsaData);

#ifdef USE_IPV6
  int fd = socket(AF_INET6, SOCK_DGRAM, 0);
#else
  SOCKET fd = socket(AF_INET, SOCK_DGRAM, 0);
#endif

  sockaddr_storage address;
  int length = sizeof(sockaddr_storage);

  char buffer[1];
  recvfrom(fd, buffer, sizeof buffer, 0, (struct sockaddr*)&address, &length);

  // Error
  char ip[NI_MAXHOST];
  char port[NI_MAXSERV];
  int rc = getnameinfo((struct sockaddr*)&address,
                       length,
                       ip,
                       sizeof(ip),
                       port,
                       sizeof(port),
                       NI_NUMERICHOST | NI_NUMERICSERV);
  if (rc)
    WSAGetLastError(); // Error Code = 10047

  std::cout << "IP: " << ip << std::endl;
  std::cout << "Port: " << port << std::endl;

// Works
#ifdef USE_IPV6
  struct sockaddr_in6* sa = (struct sockaddr_in6*)&address;
  inet_ntop(AF_INET6, &sa->sin6_addr, ip, INET6_ADDRSTRLEN);
  uint16_t port_ = ntohs(sa->sin6_port);
#else
  struct sockaddr_in* sa = (struct sockaddr_in*)&address;
  inet_ntop(AF_INET, &sa->sin_addr, ip, INET_ADDRSTRLEN);
  uint16_t port_ = ntohs(sa->sin_port);
#endif
}
一旦您这样做,您就不会再看到错误10047,您应该能够打印ip和端口缓冲区的内容并查看相应的信息

参考资料:


此问题显示的代码不符合stackoverflow.com的要求。这意味着这里的任何人都不可能最终回答这个问题;但最多只能猜测。你的问题应该显示一个最小的例子,不超过一到两页的代码(“最小”部分),其他人可以剪切/粘贴、编译、运行和复制所描述的问题(“可复制”部分),完全如图所示(这包括任何辅助信息,如程序输入)。有关详细信息,请参阅。@SamVarshavchik谢谢,我已更改了源代码。它仍然无法满足应用程序的要求。除非您对以下问题的答案是肯定的:“世界上的每个人都能完全按照所示剪切/粘贴所显示的代码吗?仅此而已,尝试编译并复制您所说的错误”——除非这个问题的答案是肯定的,否则这不是一个错误。
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>

int main(int, char **) {

  WORD wVersionRequested = MAKEWORD(2, 2);
  WSADATA wsaData;
  WSAStartup(wVersionRequested, &wsaData);

#ifdef USE_IPV6
  int fd = socket(AF_INET6, SOCK_DGRAM, 0);
#else
  SOCKET fd = socket(AF_INET, SOCK_DGRAM, 0);
#endif

  sockaddr_storage address;
  int length = sizeof(sockaddr_storage);

  char buffer[1];
  recvfrom(fd, buffer, sizeof buffer, 0, (struct sockaddr*)&address, &length);

  // Error
  char ip[NI_MAXHOST];
  char port[NI_MAXSERV];
  int rc = getnameinfo((struct sockaddr*)&address,
                       length,
                       ip,
                       sizeof(ip),
                       port,
                       sizeof(port),
                       NI_NUMERICHOST | NI_NUMERICSERV);
  if (rc)
    WSAGetLastError(); // Error Code = 10047

  std::cout << "IP: " << ip << std::endl;
  std::cout << "Port: " << port << std::endl;

// Works
#ifdef USE_IPV6
  struct sockaddr_in6* sa = (struct sockaddr_in6*)&address;
  inet_ntop(AF_INET6, &sa->sin6_addr, ip, INET6_ADDRSTRLEN);
  uint16_t port_ = ntohs(sa->sin6_port);
#else
  struct sockaddr_in* sa = (struct sockaddr_in*)&address;
  inet_ntop(AF_INET, &sa->sin_addr, ip, INET_ADDRSTRLEN);
  uint16_t port_ = ntohs(sa->sin_port);
#endif
}
sockaddr_storage address;
address.ss_family = AF_INET;