升级支持ipv4/ipv6后的Socket处理
前提条件是socket已经支持ipv4处理,需修改以下两处:
1.创建socket时
//解析是ipv4地址还是ipv6地址
struct addrinfo addrin;
struct addrinfo* pAddr = &addrin;
int nRet = getaddrinfo(m_sAddress.c_str(), nullptr, nullptr, &pAddr);
int _ai_family;
if(nRet != 0)
{
freeaddrinfo(pAddr);
_ai_family = AF_UNSPEC;
return false;
}
_ai_family = pAddr->ai_family;
// 创建主套接字
m_sockClient = socket(_ai_family, SOCK_STREAM, IPPROTO_TCP);
if(m_sockClient == INVALID_SOCKET)
{
freeaddrinfo(pAddr);
closeSocket();
CCLOG("CGameSocket:初始化失败");
return false;
}
freeaddrinfo(padder);
2.connect的时候
std::vector<std::string> ips;
struct addrinfo hints, *pAddr;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_protocol = IPPROTO_IP;
int error = getaddrinfo(m_sAddress.c_str(), nullptr, &hints, &pAddr);
if (error != 0 )
{
printf("getaddrinfo: %s\n", gai_strerror(error));
return;
}
if (pAddr->ai_family == AF_INET)
{
struct sockaddr_in* ipv4 = nullptr;
char str[32] = {0};
for (auto iter = pAddr; iter != nullptr; iter = iter->ai_next)
{
ipv4 = (struct sockaddr_in*)iter->ai_addr;
inet_ntop(AF_INET, &ipv4->sin_addr, str, 32);
ips.push_back(str);
}
}
else if(pAddr->ai_family == AF_INET6)
{
struct sockaddr_in6* ipv6 = nullptr;
char str[40] = {0};
for (auto iter = pAddr; iter != nullptr; iter = iter->ai_next)
{
ipv6 = (struct sockaddr_in6*)iter->ai_addr;
inet_ntop(AF_INET6, &ipv6->sin6_addr, str, 40);
ips.push_back(str);
}
}
int nReady;
std::vector<std::string> ipVector = ips;
if (pAddr->ai_family == AF_INET6)
{
for (auto iter = ipVector.begin(); iter!= ipVector.end(); iter++)
{
std::string ip = iter->c_str();
sockaddr_in6 sa = {0};
struct in6_addr addr = {0};
inet_pton(pAddr->ai_family, ip.c_str(), &addr);
sa.sin6_family = pAddr->ai_family;
sa.sin6_port = htons(m_wPort);
sa.sin6_addr = addr;
nReady = ::connect(m_sockClient, (sockaddr*)&sa, sizeof(sa));
if (nReady == 0) break;
}
}
else
{
std::string ip = ipVector.at(0);
sockaddr_in sa = {0};
struct in_addr addr = {0};
inet_pton(pAddr->ai_family, ip.c_str(), &addr);
sa.sin_family = pAddr->ai_family;
sa.sin_port = htons(m_wPort);
sa.sin_addr = addr;
nReady = ::connect(m_sockClient, (sockaddr*)&sa, sizeof(sa));
}
freeaddrinfo(pAddr);
if( nReady != SOCKET_ERROR )
{
//接收线程
std::thread pSocketRecv(&CGameSocket::onThreadRecv, this);
pSocketRecv.detach();
CCLOG("CTCPSocket: Connect Succeed");
}