【问题标题】:Convert IPv6 to IPv4 format in c++?在 C++ 中将 IPv6 转换为 IPv4 格式?
【发布时间】:2020-11-06 21:32:21
【问题描述】:

我正在维护一个在 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 格式,以便应用程序的其余部分正常工作?

谢谢。

【问题讨论】:

  • 尝试将硬件配置更改为仅 IPV4。删除或禁用 IPV6。
  • @cup 我确实尝试按照此示例 blog.mlinar.biz/2012/01/03/… 删除 IPv6 协议。 ,它不起作用。
  • 不起作用意味着数据未发送到 PC 或 PC 正在接收数据但未对其进行操作,因为它仍然是 IPV6。如果您执行 ipconfig,您会看到 IPV6 地址吗?如果你这样做了,那么在尝试你的程序之前你可能需要重新启动。
  • 仅供参考,我已在接收服务器网络中禁用 IPv6 协议。因此,我假设如果请求者的手机从电信公司分配了 IPv6,而在请求服务器并且没有 Ipv6 协议时,请求者的请求将回退到 IPv4 协议。但似乎情况并非如此。我想我必须创建一个新的 IPv6 套接字侦听器才能使其工作。这是我的想法
  • 抱歉,帮不了你 - 我从来没有在只在 IPV6 上传输的机器上工作过。

标签: c++ c ipv6 ipv4


【解决方案1】:

您无法将所有 IPv6 地址都转换为 IPv4 - IPv6 地址比 IPv4 地址多。解决此问题的最佳方法是更新/升级您的应用程序,以便它了解和存储 IPv6 地址。这个thread 可能有用。

【讨论】:

    【解决方案2】:

    我前段时间实施了一个可以使用 IPV4 和 IPV6 地址的解决方案。我什至确实封装了来自外部世界的属性。

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

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

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

    请看下面我几年前用 C++98 开发的代码 sn-p。

    // 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);
    
    

    你可以找到其余的here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-22
      • 2015-03-28
      • 2015-03-10
      • 2012-06-29
      • 2018-01-23
      • 2011-01-03
      • 2017-12-17
      • 1970-01-01
      相关资源
      最近更新 更多