在C中使用bind()时获取错误的IP地址

时间:2012-01-04 14:55:32

标签: c++ c sockets tcp

我在C中使用套接字编程API。在TCP客户端程序中,我使用bind(),然后使用getsockname()(在调用connect()之前)获取本地机器的IP地址和端口号。但是,我只能获取正确的端口号,同时获取错误的IP地址(零)。

所以我问是否有办法正确获取本地机器的正确IP地址(在致电connect()之前)?

5 个答案:

答案 0 :(得分:4)

没有一种简单或可移植的方式来做你想做的事情。您案件中bind()getsockname()的行为是正确的。

您的程序不应以任何方式依赖或要求主机的IP地址。如果是这样,您的程序可能会遇到一些设计问题。

问问自己,有两个网络接口,连接到两个不同网络和多个IP地址的计算机的IP地址是什么?

     Network 1                  Network 2
...-----------+--            --+-----------...
               \              /
     192.0.2.1  \            /  198.51.100.2
          eth0  +------------+  eth1
                |  Computer  |
                +------------+

问:您希望在这种情况下看到什么IP地址?

答案是没有正确的答案,你的程序甚至不应该为此烦恼。您的程序应该更关注建立通信,为此您只需要目标IP或主机名。操作系统将找到建立通信的方法(对于面向连接的流,可能能够为您提供选择与该目标通信的本地地址。)

您可以使用gethostname()检索当前主机名,并使用该名称尝试查找IP地址,但仍有很多问题:

  1. 不要求或保证主机名具有任何关联的IP地址。
  2. 在比你想象的更多的情况下,与主机名相关联的IP地址是127.0.0.1,这是没用的(大多数Linux发行版将它添加到你的/ etc / hosts文件中)。
  3. 即使您从主机名获得IP地址,它也不太可能有任何用处(如上面的案例2,或NAT后面的本地IP地址,或错误的网络接口的IP)。 / LI>

    所以,你不应该首先依赖这些信息。

答案 1 :(得分:1)

您可以使用gethostname获取主机名,然后使用gethostbyname获取IP地址。

答案 2 :(得分:1)

一种可行的方法是首先调用gethostname()然后调用gethostbyname()。

char hostname[256], ipaddress[256];
if (gethostname(hostname, sizeof(hostname)) != SOCKET_ERROR) {
    struct hostent *phe = gethostbyname(hostname);
    if (phe != NULL && phe->h_addr_list[0] != NULL) {
        struct in_addr addr;
        memcpy(&addr, phe->h_addr_list[0], sizeof(struct in_addr));
        strcpy(ipaddress, inet_ntoa(addr));
    }
}

答案 3 :(得分:1)

如果您绑定到INADDR_ANY,那么这就是您将从getsockname()获得的地址。

特别是,在具有多个接口的计算机上,套接字方使用的地址将取决于路由表和远程客户端的地址。

例如,如果您在环回接口上连接到自己,那么您将在127.0.0.1上,而如果您连接到外部的某个人,则它将是(以其中一个)您的以太网接口的地址。

正确的方法当且仅当您确实需要绑定已知地址时,才能枚举您机器的网络接口(如果您使用的是Linux,请参阅man netdevice)然后提供bind()的具体所需地址。

答案 4 :(得分:0)

您可以使用gethostip()获取主机IP地址。