編寫WinSock代碼時不推薦使用inet_addr函數的原因

編寫WinSock代碼時,相信大家一般都會使用inet_addr函數來將點分十進制字符串轉換爲sin_addr.S_un.S_addr,如下

	SOCKADDR_IN sockaddr;
	sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

但是,由於inet_addr函數沒有錯誤判斷機制,所以導致傳入錯誤的點分十進制字符串時,inet_addr函數還是會執行成功,然後會出現讓人哭笑不得的現象,如下

	SOCKADDR_IN sockaddr;
    sockaddr.sin_addr.S_un.S_addr = inet_addr("127");
    auto pAddr = inet_ntoa(sockaddr.sin_addr);
    if (pAddr != NULL)
    {
    	std::cout << pAddr << "\n";
    }
    
    sockaddr.sin_addr.S_un.S_addr = inet_addr("127.1");
	pAddr = inet_ntoa(sockaddr.sin_addr);
    if (pAddr != NULL)
    {
    	std::cout << pAddr << "\n";
    }

上述代碼在VS2017上運行結果如下
在這裏插入圖片描述
輸出的結果完全跟傳入的參數不符。

所以說,編寫WinSock代碼時,不推薦使用inet_addr函數,應該使用inet_pton函數轉換點分十進制字符串,代碼如下

	SOCKADDR_IN sockaddr;
	char szAddress[255] = { 0, };
    int nRetValue = inet_pton(AF_INET, "127", &sockaddr.sin_addr);
    if (nRetValue != 0)
    {
        auto pAddress = inet_ntop(AF_INET, &sockaddr.sin_addr, szAddress, sizeof(szAddress));
        if (pAddress != NULL)
        {
            std::cout << pAddress << '\n';
        }
    }
    
    nRetValue = inet_pton(AF_INET, "127.1", &sockaddr.sin_addr);
    if (nRetValue != 0)
    {
        auto pAddress = inet_ntop(AF_INET, &sockaddr.sin_addr, szAddress, sizeof(szAddress));
        if (pAddress != NULL)
        {
            std::cout << pAddress << '\n';
        }
    }

    nRetValue = inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
    if (nRetValue != 0)
    {
        auto pAddress = inet_ntop(AF_INET, &sockaddr.sin_addr, szAddress, sizeof(szAddress));
        if (pAddress != NULL)
        {
            std::cout << pAddress << '\n';
        }
    }

上述代碼在VS2017上的運行結果如下
在這裏插入圖片描述
可見,當輸入的點分十進制格式錯誤時,inet_pton函數返回零值,否則返回非零值。更多關於inet_pton函數的介紹可瀏覽這個網站:https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-inet_pton

至於關於inet_addr函數的介紹網站爲:https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-inet_addrinet_ntoa函數的介紹網站爲:https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-inet_ntoainet_ntop函數的介紹網站爲:https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-inet_ntop

在我看來,inet_ntoa函數和inet_ntop函數在一般的使用情況下是沒有區別,但是inet_ntoa函數不支持ipv6。轉換失敗時inet_ntoa函數和inet_ntop函數都是返回NULL。

但是呢,inet_pton函數和inet_ntop函數是Windows Vista及以後的版本才支持的,那運行在Windows XP上程序咋辦呢?(PS:別跟我說Windows XP早就沒人用了,T_T在你想不到的地方還有很多使用着Windows XP的古董機。)

由於Windows沒有提供inet_aton函數,所以呢我們不可避免地要去使用inet_addr函數。那麼我們就可以在執行inet_addr函數轉換前使用正則表達式來判斷一下字符串是否是正確的ipv4地址,代碼如下

	std::regex regexIpAddress("(?=(\\b|\\D))(((\\d{1,2})|(1\\d{1,2})|(2[0-4]\\d)|(25[0-5]))\\.){3}((\\d{1,2})|(1\\d{1,2})|(2[0-4]\\d)|(25[0-5]))(?=(\\b|\\D))");
    if (!std::regex_match("127", regexIpAddress))
    {
        std::cout << "not match\n";
    }
    else
    {
        std::cout << "match\n";
    }

    if (!std::regex_match("127.1", regexIpAddress))
    {
        std::cout << "not match\n";
    }
    else
    {
        std::cout << "match\n";
    }

    if (!std::regex_match("127.0.0.1", regexIpAddress))
    {
        std::cout << "match\n";
    }
    else
    {
        std::cout << "match\n";
    }

上述代碼在VS2017上的執行結果如下
在這裏插入圖片描述
關於C++的正則表達式庫可以查看這個網址:https://zh.cppreference.com/w/cpp/regex

以上就是本博客的全文,本人限於能力,上文中難免有錯誤的地方,若讀者發現上文的錯誤,請於評論區中指出,本人看到之後會立即修改的,謝謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章