C++创建支持IPv4/IPv6的Socket

来源:互联网 发布:手机淘宝怎么进入众筹 编辑:程序博客网 时间:2024/05/23 13:33


感谢这篇文章提供解决思路


//连接socketbool NetSelectClient::connect(const char * domain, unsigned short port, int * fd){    // domain 支持域名和IP地址    //获取socket的addr    if ( NetSelectClient::isIpv6Net( domain ) )        m_tAddr6 = NetSelectClient::getIpv6( domain, port );    else        m_tAddr4 = NetSelectClient::getIpv4( domain, port );        sockaddr* addr = NULL;    unsigned int addrSize = 0;    unsigned int inet = 0;        if ( NetSelectClient::isIpv6Net( domain ) )    {        addr = (sockaddr *)&m_tAddr6;        addrSize = sizeof( m_tAddr6 );        inet = AF_INET6;    }    else    {        addr = (sockaddr *)&m_tAddr4;        addrSize = sizeof( m_tAddr4 );        inet = AF_INET;    }        //开始执行socket流程    int sock = socket( inet, SOCK_STREAM, 0);    if ( sock < 0 )        return false;    if ( ::connect( sock, addr, addrSize ) != 0 )    {        ::close(sock);        return false;    }        if( fd )        *fd = sock;    notifyconnect( sock );    _curfds.push_back( sock );    return true;    }struct sockaddr_in NetSelectClient::getIpv4( const char* domain, unsigned short port ){    sockaddr_in addr;    //下次在这里一定要初始化addr,如果不初始化,会影响connect连接的时候出现连接错误 [ 返回-1,错误代码101,错误描述not route to host ],耽误了两天左右的时间就是为了找他,也不知道哪里出了问题    memset( &addr, 0, sizeof( addr ) );    addr.sin_family = AF_INET;    addr.sin_addr.s_addr = inet_addr( NetSelectClient::domainToIP( domain ).c_str() );    addr.sin_port = htons( port );    return addr;}struct sockaddr_in6 NetSelectClient::getIpv6( const char* domain, unsigned short port ){    sockaddr_in6 addr;    //下次在这里一定要初始化addr,如果不初始化,会影响connect连接的时候出现连接错误 [ 返回-1,错误代码101,错误描述not route to host ],耽误了两天左右的时间就是为了找他,也不知道哪里出了问题    memset( &addr, 0, sizeof( addr ) );    addr.sin6_family = AF_INET6;    inet_pton(AF_INET6, NetSelectClient::domainToIP( domain ).c_str(), &addr.sin6_addr);    addr.sin6_port = htons(port);    return addr;}//判断是否IPv6网络bool NetSelectClient::isIpv6Net(const char* domainStr){    bool isIPV6Net = false;        struct addrinfo *result = NULL, *curr;        struct sockaddr_in6 dest;    bzero(&dest, sizeof(dest));        dest.sin6_family  = AF_INET6;        int ret = getaddrinfo(domainStr,NULL,NULL,&result);    if (ret == 0)    {        for (curr = result; curr != NULL; curr = curr->ai_next)        {            switch (curr->ai_family)            {                case AF_INET6:                {                    isIPV6Net = true;                    break;                }                case AF_INET:                                        break;                                    default:                    break;            }        }    }        freeaddrinfo(result);        return isIPV6Net;}//域名解析std::string NetSelectClient::domainToIP(const char* pDomain){    if (NetSelectClient::isIpv6Net(pDomain))    {        struct addrinfo hint;        memset(&hint, 0x0, sizeof(hint));        hint.ai_family = AF_INET6;        hint.ai_flags = AI_V4MAPPED;                addrinfo* answer = NULL;        getaddrinfo(pDomain, NULL, &hint, &answer);                if (answer != NULL)        {            char hostname[1025] = "";                        getnameinfo(answer->ai_addr,answer->ai_addrlen,hostname,1025,NULL,0,0);                        char ipv6[128] = "";            memcpy(ipv6,hostname,128);                        return ipv6;        }                freeaddrinfo(answer);    }    else    {        struct hostent* h = gethostbyname(pDomain);        if( h != NULL )        {            unsigned char* p = (unsigned char *)(h->h_addr_list)[0];            if( p != NULL )            {                char ip[16] = {0};                sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);                return ip;            }        }    }    return "";}


0 0
原创粉丝点击