首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从`sockaddr_storage`实例中检索IP和端口?

如何从`sockaddr_storage`实例中检索IP和端口?
EN

Stack Overflow用户
提问于 2020-08-10 17:16:39
回答 1查看 469关注 0票数 0

如何使用sockaddr_storage实例( getnameinfo() (ref) )检索IP和端口?

当我使用inet_ntop时,它正常工作,但是当我用getnameinfo函数替换它时,它返回了一个错误:

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

代码语言:javascript
运行
复制
#ifdef USE_IPV6
int fd = socket(AF_INET6, SOCK_DGRAM, 0);
#else
int fd = socket(AF_INET, SOCK_DGRAM, 0);
#endif

sockaddr_storage address;
int length = sizeof address;

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

// 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
EN

Stack Overflow用户

回答已采纳

发布于 2020-08-12 00:36:54

我看了你的问题,并能够重现你所犯的错误。

可复制的例子:

代码语言:javascript
运行
复制
#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
}

问题在于您没有设置ss_family结构的sockaddr_storage字段。

要解决这个问题,需要在ss_family中指定sockaddr_storage值,如下所示:

代码语言:javascript
运行
复制
sockaddr_storage address;
address.ss_family = AF_INET;

完成此操作后,您将不再看到错误10047,您应该能够打印ip和端口缓冲区的内容并查看相应的信息。

参考文献:

票数 1
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63344936

复制
相关文章

相似问题

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