【博客265】网络编程中的INADDR_ANY作用

本文详细解析网络编程中INADDR_ANY的使用场景及优势,对比127.0.0.1与具体网卡地址,阐述其在服务器监听中的作用,包括代码示例与实践结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内容: 记录网络编程中,服务器的监听地址设置为 "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不同,每次都需要手动修改
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值