如何使用套接字地址获取自己的IP地址?

Jul*_*lhé 7 c sockets linux networking

我想获取我的程序启动的计算机的IP地址,然后能够将其发送到客户端,但我总是得到0.0.0.1而不是真正的IP地址(例如127.0.0.1).

我目前能够获得端口,但不能获得IP地址.

我怎么才能得到它?

最好的解决方案是能够获得它sockaddr_in.这是我目前正在做的事情:

int open_connection(char* ip, int* port)
{
  int                   sock;
  struct sockaddr_in    sin;
  socklen_t             len;
  int                   i;

  i = 0;
  len = sizeof(sin);
  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    return (-1);
  bzero(&sin, sizeof(struct sockaddr_in));
  sin.sin_family = AF_INET;
  if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0)
    perror("Error on bind");
  if (getsockname(sock, (struct sockaddr *)&sin, &len) != 0)
    perror("Error on getsockname");
  strcpy(ip, inet_ntoa(sin.sin_addr)); // IP = 0.0.0.0
  *port = sin.sin_port;
  return (sock);
}
Run Code Online (Sandbox Code Playgroud)

编辑:我理解我用我的思维方式走错了方向.所以我的问题是:获取自己的IP地址的最佳方法是什么?

Rem*_*eau 11

当你bind()的套接字为0.0.0.0时,这是套接字在调用时唯一可用的IP getsockname().这意味着套接字绑定到所有本地接口.为了从套接字获取特定IP,必须将其绑定到特定IP.

无论如何,使用套接字API来获取计算机的本地IP是错误的方法.一个常见的错误是使用gethostname()gethostbyname()getaddrinfo()获取本地IP列表.通常这有效,但它有一些隐藏的陷阱,可以导致虚假的信息,但人们往往忽略这一事实,或者甚至不知道它一开始(我多年不知道它,但后来我学得更好).

相反,您确实应该使用特定于平台的API来枚举本地网络接口.这将提供更可靠的信息.Windows有GetAdaptersInfo()GetAdaptersAddresses().其他平台有getifaddrs().这些将告诉您哪些本地IP可用.然后,您可以将bind()套接字设置为0.0.0.0,以便接受任何这些IP上的客户端,或bind()接受特定IP以仅接受该IP上的客户端.


Hav*_*ard 5

套接字 API 允许您枚举分配给网络接口的 IP 地址,但如果您从路由器后面连接到 Internet,它不会告诉您“真实 IP”是什么。

要知道它的唯一方法是询问外面的人。FileZilla FTP Server 这样的服务器就是这样做的。他们指导您配置URL为“ip.php”脚本像这样一个在服务器的设置,使其可以要求互联网什么的公网IP地址,在被动模式下使用。

您还可以考虑使用STUN,一种在 VoIP 中广泛使用的协议来发现公共 IP。