我最近遇到this blog post,它描述了使用libev的TCP服务器客户端。服务器使用INADDR_ANY
绑定到我熟悉的接口。但是,我也很惊讶在客户端代码中看到INADDR_ANY
。客户端代码上的相关代码如下:
// Create client socket
if( (sd = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
{
perror("socket error");
return -1;
}
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT_NO);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
// Connect to server socket
if(connect(sd, (struct sockaddr *)&addr, sizeof addr) < 0)
{
perror("Connect error");
return -1;
}
特别是我对这一行感兴趣:
addr.sin_addr.s_addr = htonl(INADDR_ANY);
在服务器端,我知道INADDR_ANY
会将端口绑定到所有可用的接口,但是我不确定在客户端这有何意义。最后,客户端将需要在特定接口上进行连接。以前,我总是指定IP地址或使用INADDR_LOOPBACK
。
The Linux IP man page不在客户端使用INADDR_ANY
。我确实找到了another Stack Overflow post here,它表示OP应该在客户端使用INADDR_ANY
,但没有给出任何理由或解释。
那么这到底在做什么?是否尝试所有接口,直到找到一个可用于连接的端口?这按什么顺序发生?
感谢您的回答!
这是nos在评论中提供的答案。如果nos回来并将其发布为答案,我会将nos的帖子标记为答案并删除它。
INADDR_ANY通常定义为0。即IP地址0.0.0.0。RFC 1122表示这意味着“此网络上的主机”。 linux IP堆栈似乎只是将其路由到回送接口。 (例如,尝试ping 0.0.0.0甚至只是ping 0)。我想说作者打错了字,应该使用了INADDR_LOOPBACK。
似乎您的问题不是关于“客户端”,而是关于bind
与connect
。
INADDR_ANY
可以与客户端和服务器上的bind
一起使用。将其与connect()
一起使用是没有意义的,应该会导致连接失败。
在客户端,使用INADDR_ANY是多余的,但是我看到了一些代码,我想这是为了“完整性”。如果您要强制使用特定的接口,例如可以在客户端指定接口。在多宿主计算机中。
绑定到客户端的端口也不常见。通常最好让系统找到可用的端口,否则程序可能会由于客户端或服务器正在使用该端口而失败。
[BSD有一个古老的约定,即连接到INADDR_ANY意味着您要连接到回送网络。 linux网络代码显式支持此功能(在this file中搜索INADDR_ANY)。我不知道还有哪些其他操作系统支持或不支持它。