簡體   English   中英

在c++中將IPv6格式轉換為IPv4格式?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM