内容: 记录网络编程中,服务器的监听地址设置为 "INADDR_ANY"的作用
监听地址为127.0.0.1时:
1、此时只有本地可以发起连接,不同主机不可以发起连接,因为127.0.0.1是环回地址。
2、当监听为127.0.0.1时,报文并不需要层层封装,会直接交付本机协议栈,因为环回地址代表通信的
一般是本机进程之间的通信。
监听地址为某网卡地址,比如:192.168.X.X时:
1、此时监听的是本机某网卡的地址,那么只有目的地址为此地址的才可以发起连接
2、此时像127.0.0.1地址发起连接,无法与服务器建立连接
监听地址为INADDR_ANY时:
1、此时可以接受所有客户连接,但是本质是监听了本机所有网卡的地址,因此本地环回的和外部的连接都
可以建立
代码实例一:监听127.0.0.1地址,对本机网卡地址发起连接
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
struct sockaddr_in serveraAddr , clientAddr;
socklen_t clientAddrLen;
int listen_fd = 0,sockfd = 0;
int ret = 0;
int len = 0;
char buff[BUFSIZ] = {0};
listen_fd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == listen_fd)
{
perror("socket:");
return -1;
}
memset(&serveraAddr,0,sizeof(struct sockaddr_in));
serveraAddr.sin_family = AF_INET;
serveraAddr.sin_addr.s_addr = htonl(0x7f000001); //0x7f000001 = 127.0.0.1
serveraAddr.sin_port = htons(55555);
ret = bind(listen_fd,(struct sockaddr*)&serveraAddr,sizeof(serveraAddr));
if(-1 == ret)
{
perror("bind:");
return -1;
}
listen(listen_fd,1);
clientAddrLen = sizeof(struct sockaddr_in);
sockfd = accept(listen_fd,(struct sockaddr*)&clientAddr,&clientAddrLen);
if(-1 == sockfd)
{
perror("accept:");
return -1;
}
printf("connect %s %d successful\n",inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port));
while(1)
{
memset(buff,0,BUFSIZ);
len = read(sockfd,buff,BUFSIZ);
if(len > 0)
{
printf("read data: %s\n",buff);
}
}
return 0;
}
结果:
1、对环回地址发起连接:
luzejia@ubuntu:~$ nc -v localhost 55555
Connection to localhost 55555 port [tcp] succeeded!
结果:成功建立连接!
2、对网卡地址发起连接:
查看某块网卡地址:
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.72.154 netmask 255.255.255.0 broadcast 192.168.72.255
inet6 fe80::34fb:3623:3a50:66ff prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:ce:be:44 txqueuelen 1000 (Ethernet)
RX packets 1380 bytes 610575 (610.5 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 515 bytes 64830 (64.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
发起连接:
luzejia@ubuntu:~$ nc -v 192.168.72.154 55555
nc: connect to 192.168.72.154 port 55555 (tcp) failed: Connection refused
结果:无法建立连接
代码实例二:监听INADDR_ANY地址,对本机网卡和环回地址发起连接
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
struct sockaddr_in serveraAddr , clientAddr;
socklen_t clientAddrLen;
int listen_fd = 0,sockfd = 0;
int ret = 0;
int len = 0;
char buff[BUFSIZ] = {0};
listen_fd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == listen_fd)
{
perror("socket:");
return -1;
}
memset(&serveraAddr,0,sizeof(struct sockaddr_in));
serveraAddr.sin_family = AF_INET;
serveraAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraAddr.sin_port = htons(55555);
ret = bind(listen_fd,(struct sockaddr*)&serveraAddr,sizeof(serveraAddr));
if(-1 == ret)
{
perror("bind:");
return -1;
}
listen(listen_fd,1);
clientAddrLen = sizeof(struct sockaddr_in);
sockfd = accept(listen_fd,(struct sockaddr*)&clientAddr,&clientAddrLen);
if(-1 == sockfd)
{
perror("accept:");
return -1;
}
printf("connect %s %d successful\n",inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port));
while(1)
{
memset(buff,0,BUFSIZ);
len = read(sockfd,buff,BUFSIZ);
if(len > 0)
{
printf("read data: %s\n",buff);
}
}
return 0;
}
结果:
1、对环回地址发起连接:
luzejia@ubuntu:~$ nc -v localhost 55555
Connection to localhost 55555 port [tcp] succeeded!
结果:成功建立连接!
2、对网卡地址发起连接:
查看某块网卡地址:
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.72.154 netmask 255.255.255.0 broadcast 192.168.72.255
inet6 fe80::34fb:3623:3a50:66ff prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:ce:be:44 txqueuelen 1000 (Ethernet)
RX packets 1380 bytes 610575 (610.5 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 515 bytes 64830 (64.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
发起连接:
luzejia@ubuntu:~$ nc -v 192.168.72.154 55555
Connection to 192.168.72.154 55555 port [tcp] succeeded!
结果:可以成功建立连接!
代码实例三:监听INADDR_ANY地址与监听0.0.0.0地址区别:
1、监听0.0.0.0和监听INADDR_ANY在接收连接上有相同的效果
2、重启服务器时,两者出现差别:
* 监听0.0.0.0时:(time_wait的后遗症!!)
luzejia@ubuntu:~$ ./a.out
bind:: Address already in use
此时出现bind错误,端口和地址被使用,暂未释放!
* 监听INADDR_ANY时:
luzejia@ubuntu:~$ ./a.out
| (光标闪烁,等待连接)
此时无错误提示,依旧可以接受连接
使用INADDR_ANY的好处:
1、使得代码更具有兼容性,更具备异地部署特性,更具通用性
2、如果监听特定地址,当程序部署到其它主机时,由于IP不同,每次都需要手动修改