用c++将IPv6转换为IPv4格式



我正在维护一个在IPv4格式上运行良好的旧系统,我发现当请求者来自IPv6时,侦听器没有触发。我有以下代码行

SOCKADDR_IN SocketAddr;
INT nBufferSize=sizeof(SocketAddr);
hConnectSocket=WSAAccept(m_hListenSocket,(SOCKADDR *)&SocketAddr,&nBufferSize,NULL,NULL);

if (hConnectSocket==INVALID_SOCKET) return false;

我也在谷歌上搜索过,我知道我应该使用SOCKADDR_IN6进行IPv6。是否可以将SOCKADDR_IN6转换为SOCKADDR_IN格式,以便应用程序的其余部分正常工作?

谢谢。

无法将所有IPv6地址转换为IPv4-IPv6地址比IPv4地址多。解决此问题的最佳方法是更新/升级应用程序,使其了解并存储IPv6地址。这个线程可能很有用。

我不久前实现了一个可以使用IPV4和IPV6地址的解决方案。我甚至从外部世界概括了这个属性。

程序的其余部分应该只知道套接字。如果您的代码接受IPV6或IPV4格式的地址并不重要(在接受之后(。

重要的一点是,您需要用AF_UNSPEC指定ai_family。然后它将处理两个地址族。对于accept函数,您可以切换一个足够大的参数来容纳两种地址类型。

我不确定,但也许这对你有帮助。

请参阅以下几年前我在C++98中开发的代码片段。

// The following structures are used in order to be independent from the internet address families
// e.g. IPV4 or IPV6.  The basic original functions have been designed for IPV4 only. 
// But now we are in the age of IPV6. And we need to have means to deal with both address types
// So we have one Data type, that can hold both IPV4 and IPV6 (because it has the length of the 
// larger IPV6 address). The pointer of this structure can be casted to the original data type
// that the functions always expected.
// The first field in the structures denotes the IP Address Family
// This is the big storage that can hold either a IPV4 or a IPV6 address
typedef struct sockaddr_storage SocketAddressStorage;
// This Type can hold the length of the IP Address container
typedef socklen_t SocketAddressStorageLength;

// This type is the Socket Address that OS function expect. We will cast the pointer of the big
// data type to this one
typedef struct sockaddr SocketAddress;
// The next 2 are specific address containers for either IPV4 or IPV6. 
// One of them will be a part of the big "struct sockaddr_storage"
typedef struct sockaddr_in SocketAddressInternetIPV4;
typedef struct sockaddr_in6 SocketAddressInternetIPV6;

// We use the big structure that can hold an IPV4 and IPV6 address
// because we do not know, who is contacting this node
SocketAddressStorage addressOfCommunicationPartner;
// Get the length of the above define data structure
SocketAddressStorageLength socketAddressStorageLength = sizeof(addressOfCommunicationPartner);

// Accept the connection request from a client
// handle is the filedescriptor bound to this node and listening for connection requests
// The function will return a new file descriptor for the connected socket. This is a specific socket
// for the just established connection. The handle will continue to listen for more connection requests
// So this is a factory. We are listening for connection requests and if we get one, we create a new
// file descriptor for the specific communication purposes
// The information of the foreign node will be put in the "addressOfCommunicationPartner"
// Accept the connection request from a client
//lint -e{740,929,1924}
const Handle connectionHandle = accept(handle, reinterpret_cast<SocketAddress *>(&addressOfCommunicationPartner), &socketAddressStorageLength);
// Check, if connection could be established and we have a valid file descriptor
if (connectionHandle > null<Handle>())
{
// Now we want to get the IP address of the partner. Can be IPv4 or IPv6
// The following old style C String can hold both IPv4 and IPv6 address strings
mchar ipAddressCString[INET6_ADDRSTRLEN+1];

// This is a pointer into the address structure of the communication partner
// It points either to sin_addr for IPv4 or sin6_addr for IPv6
const void *ipAddressPEitherV4orV6;
// This will contain the IP Version as a string
std::string ipVersion;

// Now check, what family, what type of IP adress we have
//lint -e{911,1960}
if (AF_INET == addressOfCommunicationPartner.ss_family)
{
// So, it is IPv4. Remember that
ipVersion = "IPv4";
// Get a pointer to the appropriate element of the struct, which contains IP address info. And this depending on the IP Family/Type
//lint --e{740,925,929}     Yes indeed, an unusual pointer cast
ipAddressPEitherV4orV6 = static_cast<const void *>(  &((reinterpret_cast<const SocketAddressInternetIPV4 *const>(&addressOfCommunicationPartner))->sin_addr)  );
}
else
{
// It is IPv6. Remember that
ipVersion = "IPv6";                     
// Get a pointer to the appropriate element of the struct, which contains IP address info. And this depending on the IP Family/Type
//lint --e{740,925,929}  Yes indeed, an unusual pointer cast
ipAddressPEitherV4orV6 = static_cast<const void *>(  &((reinterpret_cast<const SocketAddressInternetIPV6 *const>(&addressOfCommunicationPartner))->sin6_addr)  );
}

// Convert native IP address format to readable C-String
//lint -e{917,1960}
if (null<mchar *>() == inet_ntop(addressOfCommunicationPartner.ss_family, ipAddressPEitherV4orV6, ipAddressCString, sizeof(ipAddressCString)))
{
// If this did not work then we will not show any IP Address. We can live with that
ipAddressCString[0] = 'x0';
}


// Debug Output
{
static long i=1;
ui << "Connection accepted " << i << " " << ipVersion << " " << ipAddressCString << " " << machineNetworkAddressInfo.portNumberString << std::endl;
i++;
}



// So. The connection request was established. We gathered all information

// Create a new TCP connection
TcpConnectionBase *tcpConnectionBase =tcpConnectionFactory->createInstance(machineNetworkAddressInfo.portNumberString, connectionHandle);
// And put a pointer to it in our internal list of Tcp Connection
tcpConnection.push_back(tcpConnectionBase);

你可以在这里找到剩下的

最新更新