• 支持ipV6和ipV4的客户端编程


       ipv4和ipv6在socket初始化的时候是不一样的。

      ipv4 socket初始化:

    int CClient::InitSocket(CString strIP, short portNum)
    {
        WSADATA wsd; 
        SOCKADDR_IN servAddr; 
        int retVal; 
        //初始化套结字动态库  
        if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
        {
            return -1;
        }
        //创建套接字  
        m_sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (INVALID_SOCKET == m_sHost)
        {
            WSACleanup();//释放套接字资源  
            return  -1;
        }
    
        //设置服务器地址  
        servAddr.sin_family = AF_INET;
        servAddr.sin_addr.s_addr = inet_addr((LPCTSTR)strIP);
        servAddr.sin_port = htons(portNum);
        int nServAddlen = sizeof(servAddr);
    
        //设置非阻塞方式连接
        unsigned long ul = 1;
        retVal = ioctlsocket(m_sHost, FIONBIO, (unsigned long*)&ul);
        if (retVal == SOCKET_ERROR) return 0;
    
        //连接服务器  
        retVal = connect(m_sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr));
    
        if (retVal == 0)
        {
    
        }
        else
        {
            int iErr = GetLastError();
            if (WSAEWOULDBLOCK == iErr)
            {
                struct timeval timeout;
                fd_set r;
    
                FD_ZERO(&r);
                FD_SET(m_sHost, &r);
                timeout.tv_sec = 1; 
                timeout.tv_usec = 0;
                retVal = select(m_sHost + 1, NULL, &r, NULL, &timeout);
                if (retVal <= 0)
                {
                    closesocket(m_sHost); //关闭套接字  
                    WSACleanup(); //释放套接字资源  
                    return -1;
                }
            }
        }
    
        //退出  
        return 0;
    }

    ipv6 socket初始化:

    int CClient::InitSocket(CString strIP, short portNum)
    {
        WSADATA wsd;
        struct sockaddr_in6 servAddr_in6; 
        int retVal; 
        int nServAddlen;
        
        //初始化套结字动态库  
        if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
        {
            return -1;
        }
    
        sprintf_s(m_szIP, sizeof(m_szIP), strIP);
    
        memset(&servAddr_in6, 0, sizeof(struct sockaddr_in6));
    
        //创建套接字  
        m_sHost = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
        if (INVALID_SOCKET == m_sHost)
        {
            return  -1;
        }
    
        //设置服务器地址  
        servAddr_in6.sin6_family = AF_INET6;
    
        if (!inet_pton(AF_INET6, m_szIP, &servAddr_in6.sin6_addr.s6_addr))
        {
            closesocket(m_sHost); //关闭套接字 
            WSACleanup(); //释放套接字资源 
            return  -1;
        }
        
        //设置非阻塞方式连接
        unsigned long ul = 1;
        retVal = ioctlsocket(m_sHost, FIONBIO, (unsigned long*)&ul);
        if (retVal == SOCKET_ERROR) return 0;
        
        servAddr_in6.sin6_port = htons(portNum);
        nServAddlen = sizeof(servAddr_in6);
        //连接服务器  
        retVal = connect(m_sHost, (LPSOCKADDR)&servAddr_in6, (socklen_t)nServAddlen);
    
       if (retVal == 0)
        {
    
        }
        else
        {
            int iErr = GetLastError();
            if (WSAEWOULDBLOCK == iErr)
            {
                struct timeval timeout;
                fd_set r;
    
                FD_ZERO(&r);
                FD_SET(m_sHost, &r);
                timeout.tv_sec = 1; 
                timeout.tv_usec = 0;
                retVal = select(m_sHost + 1, NULL, &r, NULL, &timeout);
                if (retVal <= 0)
                {
                    closesocket(m_sHost); //关闭套接字  
                    WSACleanup(); //释放套接字资源  
                    return -1;
                }
            }
        }
    
        //退出  
        return 0;
    }

    将上面的逻辑合二为一:

    int CClient::InitSocket(CString strIP, short portNum)
    {
        WSADATA wsd;
        struct sockaddr_in6 servAddr_in6;
        SOCKADDR_IN servAddr;
        int retVal;
        int nServAddlen;
        
        //初始化套结字动态库  
        if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
        {
            return -1;
        }
    
        sprintf_s(m_szIP, sizeof(m_szIP), strIP);
    
        memset(&servAddr, 0, sizeof(servAddr));
        memset(&servAddr_in6, 0, sizeof(struct sockaddr_in6));
    
        //设置非阻塞方式连接
        unsigned long ul = 1;
        retVal = ioctlsocket(m_sHost, FIONBIO, (unsigned long*)&ul);
        if (retVal == SOCKET_ERROR) return 0;
        if (TRUE == is_string_ipaddr_ipv4(m_szIP, &servAddr.sin_addr))
        {
            //创建套接字  
            m_sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if (INVALID_SOCKET == m_sHost)
            {
                WSACleanup();//释放套接字资源  
                return  -1;
            }
    
            //设置服务器地址  
            servAddr.sin_family = AF_INET;
            servAddr.sin_addr.s_addr = inet_addr(m_szIP);
            servAddr.sin_port = htons(portNum);
            nServAddlen = sizeof(servAddr);
            //连接服务器  
            retVal = connect(m_sHost, (LPSOCKADDR)&servAddr, (socklen_t)nServAddlen);
        }
        else
        {
            //创建套接字  
            m_sHost = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
            if (INVALID_SOCKET == m_sHost)
            {
                return  -1;
            }
    
            //设置服务器地址  
            servAddr_in6.sin6_family = AF_INET6;
    
            if (!inet_pton(AF_INET6, m_szIP, &servAddr_in6.sin6_addr.s6_addr))
            {
                closesocket(m_sHost); //关闭套接字 
                WSACleanup(); //释放套接字资源 
                return  -1;
            }
            servAddr_in6.sin6_port = htons(portNum);
            nServAddlen = sizeof(servAddr_in6);
            //连接服务器  
            retVal = connect(m_sHost, (LPSOCKADDR)&servAddr_in6, (socklen_t)nServAddlen);
        }
    
       if (retVal == 0)
        {
    
        }
        else
        {
            int iErr = GetLastError();
            if (WSAEWOULDBLOCK == iErr)
            {
                struct timeval timeout;
                fd_set r;
    
                FD_ZERO(&r);
                FD_SET(m_sHost, &r);
                timeout.tv_sec = 1;
                timeout.tv_usec = 0;
                retVal = select(m_sHost + 1, NULL, &r, NULL, &timeout);
                if (retVal <= 0)
                {
                    closesocket(m_sHost); //关闭套接字  
                    WSACleanup(); //释放套接字资源  
                    return -1;
                }
            }
        }
    
        //退出  
        return 0;
    }

    判断一个ip是不是ipv4的

    /*判断传入的字符串是否为ipv4格式的
    */
    bool CClient::is_string_ipaddr_ipv4(const char* str_ipv4, struct in_addr *ip)
    {
        int32 ret = -1;
        struct in_addr tmp_ip;
    
        memset(&tmp_ip, 0, sizeof(struct in_addr));
    
        if (NULL == str_ipv4)
        {
            return false;
        }
    
        if (0 == *str_ipv4)
        {
            return false;
        }
    
        ret = inet_pton(AF_INET, str_ipv4, &tmp_ip);
        if (0 == ret)
        {
            return false;
        }
        else if (ret < 0)
        {
            return false;
        }
        else
        {
            if (NULL != ip)
            {
                memcpy(ip, (void *)&tmp_ip, sizeof(struct in_addr));
            }
    
            return true;
        }
    }
    高山流水,海纳百川!
  • 相关阅读:
    爬虫笔记:PyQuery模块(七)
    25丨固若金汤的根本(下):数字签名与证书
    爬虫笔记:Beautiful Soup 使用(六)
    24丨固若金汤的根本(上):对称加密与非对称加密
    爬虫笔记:requests模块使用(四)
    五安全篇(7讲)23-TLS又是什么?
    爬虫笔记:http请求详解(三)
    22丨冷链周转:HTTP的缓存代理
    python中expandtabs()函数的用法
    Python全栈工程师(while、占位符)
  • 原文地址:https://www.cnblogs.com/ahcc08/p/8279977.html
Copyright © 2020-2023  润新知