编写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

以上就是本博客的全文,本人限于能力,上文中难免有错误的地方,若读者发现上文的错误,请于评论区中指出,本人看到之后会立即修改的,谢谢。

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