我在C中使用套接字编程API。在TCP客户端程序中,我使用bind()
,然后使用getsockname()
(在调用connect()
之前)获取本地机器的IP地址和端口号。但是,我只能获取正确的端口号,同时获取错误的IP地址(零)。
所以我问是否有办法正确获取本地机器的正确IP地址(在致电connect()
之前)?
答案 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 :(得分: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地址。