![](/img/trans.png)
[英]How to convert IP address (both ipv4 and ipv6) to binary in C++?
[英]Convert IPv6 to IPv4 format in c++?
我正在維護一個在 IPv4 格式上運行良好的舊系統,我發現當請求者來自 IPv6 時,偵聽器沒有觸發。 我有以下代碼行
SOCKADDR_IN SocketAddr;
INT nBufferSize=sizeof(SocketAddr);
hConnectSocket=WSAAccept(m_hListenSocket,(SOCKADDR *)&SocketAddr,&nBufferSize,NULL,NULL);
if (hConnectSocket==INVALID_SOCKET) return false;
我也用谷歌搜索,我知道我應該為 IPv6 使用 SOCKADDR_IN6。 是否可以將 SOCKADDR_IN6 轉換為 SOCKADDR_IN 格式,以便應用程序的 rest 可以工作?
謝謝。
您無法將所有 IPv6 地址都轉換為 IPv4 - IPv6 地址多於 IPv4 地址。 解決此問題的最佳方法是更新/升級您的應用程序,使其理解和存儲 IPv6 地址。 這個線程可能有用。
我前段時間實施了一個可以使用 IPV4 和 IPV6 地址的解決方案。 我什至確實從外界封裝了該屬性。
該程序的 rest 應該只知道 sockets。如果您的代碼接受 IPV6 或 IPV4 格式的地址並不重要/接受后)。
重要的一點是您需要使用AF_UNSPEC
指定ai_family
。 然后它將處理兩個地址族。 而對於 accept function,你可以傳遞一個足夠大的參數來容納兩種地址類型。
我不確定,但也許這可以幫助你。
請看下面我幾年前用 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);
您可以在這里找到 rest
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.