INADDR_ANY的確切含義


   INADDR_ANY就是inet_addr("0.0.0.0")

        首先,需要明確的是當服務器的監聽地址是INADDR_ANY時設置的是服務器的IP地址。

   其次,當服務器的監聽地址是INADDR_ANY時含義是讓服務器端計算機上的所有網卡的IP地址都可以作為服務器IP地址,也即監聽外部客戶端程序發送到服務器端所有網卡的網絡請求。

    比如,我的網絡為:192.168.1.102. 於是就有下面的程序:

        服務端:

#include <stdio.h>
#include <winsock2.h> // winsock接口
#pragma comment(lib, "ws2_32.lib") // winsock實現

int main()
{
    WORD wVersionRequested;  // 雙字節,winsock庫的版本
    WSADATA wsaData;         // winsock庫版本的相關信息
    
    wVersionRequested = MAKEWORD(1, 1); // 0x0101 即:257
    

    // 加載winsock庫並確定winsock版本,系統會把數據填入wsaData中
    WSAStartup( wVersionRequested, &wsaData );
    

    // AF_INET 表示采用TCP/IP協議族
    // SOCK_STREAM 表示采用TCP協議
    // 0是通常的默認情況
    unsigned int sockSrv = socket(AF_INET, SOCK_STREAM, 0);

    SOCKADDR_IN addrSrv;

    addrSrv.sin_family = AF_INET; // TCP/IP協議族
    addrSrv.sin_addr.S_un.S_addr = INADDR_ANY; //inet_addr("0.0.0.0"); 
    addrSrv.sin_port = htons(8888); // socket對應的端口

    // 將socket綁定到某個IP和端口(IP標識主機,端口標識通信進程)
    bind(sockSrv,(SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

    // 將socket設置為監聽模式,5表示等待連接隊列的最大長度
    listen(sockSrv, 5);

    SOCKADDR_IN addrClient;
    int len = sizeof(SOCKADDR);

    while(1)
    {
        // sockSrv為監聽狀態下的socket
        // &addrClient是緩沖區地址,保存了客戶端的IP和端口等信息
        // len是包含地址信息的長度
        // 如果客戶端沒有啟動,那么程序一直停留在該函數處
        unsigned int sockConn = accept(sockSrv,(SOCKADDR*)&addrClient, &len);
        
        char sendBuf[100] = {0};
        sprintf(sendBuf,"%s", inet_ntoa(addrClient.sin_addr)); // 將客戶端的IP地址保存下來
        send(sockConn, sendBuf, strlen(sendBuf) + 1, 0); // 發送數據到客戶端,最后一個參數一般設置為0

        char recvBuf[100] = {0};
        recv(sockConn, recvBuf, 100, 0); // 接收客戶端數據,最后一個參數一般設置為0
        printf("%s\n", recvBuf);
        closesocket(sockConn);
    }
        
    closesocket(sockSrv);
    WSACleanup();
    
    return 0;
}

客戶端:

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")

int main()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    wVersionRequested = MAKEWORD(1, 1);
    
    WSAStartup( wVersionRequested, &wsaData );

    SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.102");
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(8888);
    int ret = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

    char recvBuf[100] = {0};
    recv(sockClient, recvBuf, 100, 0);
    printf("%s\n", recvBuf);
    send(sockClient, "hello world", strlen("hello world") + 1, 0);

    closesocket(sockClient);
    WSACleanup();

    return 0;
}

當然客戶端也可以用回測地址(設服務端與客戶端在同一台機子上):

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")

int main()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    wVersionRequested = MAKEWORD(1, 1);
    
    WSAStartup( wVersionRequested, &wsaData );

    SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(8888);
    int ret = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

    char recvBuf[100] = {0};
    recv(sockClient, recvBuf, 100, 0);
    printf("%s\n", recvBuf);
    send(sockClient, "hello world", strlen("hello world") + 1, 0);

    closesocket(sockClient);
    WSACleanup();

    return 0;
}

  當然啦,如果服務端用192.168.1.102作為監聽IP,客戶端用192.168.1.102去connect,  那也是可以的。

 

"將sin_addr設置為INADDR_ANY"的含義是什么?

問:

  很多書上都說“將sin_addr設置為INADDR_ANY,則表示所有的IP地址,也即所有的計算機”,這樣的解說讓人費解。

答:

  INADDR_ANY轉換過來就是0.0.0.0,泛指本機的意思,也就是表示本機的所有IP,因為有些機子不止一塊網卡,多網卡的情況下,這個就表示所有網卡ip地址的意思。

  當服務器的監聽地址是INADDR_ANY時,意思不是監聽所有的客戶端IP。而是服務器端的IP地址可以隨意配置,這樣使得該服務器端程序可以運行在任意計算機上,可使任意計算機作為服務器,便於程序移植。將INADDR_ANY換成127.0.0.1也可以達到同樣的目的。這樣,當作為服務器的計算機的IP有變動或者網卡數量有增減,服務器端程序都能夠正常監聽來自客戶端的請求。我是這么理解的。

  比如一台電腦有3塊網卡,分別連接三個網絡,那么這台電腦就有3個ip地址了,如果某個應用程序需要監聽某個端口,那他要監聽哪個網卡地址的端口呢?如果綁定某個具體的ip地址,你只能監聽你所設置的ip地址所在的網卡的端口,其它兩塊網卡無法監聽端口,如果我需要三個網卡都監聽,那就需要綁定3個ip,也就等於需要管理3個套接字進行數據交換,這樣豈不是很繁瑣?所以出現INADDR_ANY,你只需綁定INADDR_ANY,管理一個套接字就行,不管數據是從哪個網卡過來的,只要是綁定的端口號過來的數據,都可以接收到。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM