C++ Asio同步IPv6 UDP服务器

C++ Asio同步IPv6 UDP服务器,c++,boost,network-programming,boost-asio,asio,C++,Boost,Network Programming,Boost Asio,Asio,我正在制作一个简单的UDP IPv6服务器,用于打印远程端点发送的UDP数据包的版本。但是这个代码的行为很奇怪。发送IPv6和IPv4数据包时,它正在打印IPv6。我做错了什么?[在Win10中使用数据包发送器便携式6.2.3(127.0.0.1和::1)进行测试] #包括 #包括 #包括“udp_peer.h” #包括 asio::io_context ioContext; asio::io_上下文::工作人员(ioContext); void runServer() { ioContext.

我正在制作一个简单的UDP IPv6服务器,用于打印远程端点发送的UDP数据包的版本。但是这个代码的行为很奇怪。发送IPv6和IPv4数据包时,它正在打印
IPv6
。我做错了什么?[在Win10中使用数据包发送器便携式6.2.3(127.0.0.1和::1)进行测试]

#包括
#包括
#包括“udp_peer.h”
#包括
asio::io_context ioContext;
asio::io_上下文::工作人员(ioContext);
void runServer()
{
ioContext.run();
}
int main()
{
asio::ip::udp::endpoint mUDPep(asio::ip::udp::v6(),321);
asio::ip::udp::socket mUDPsock(ioContext);
std::线程(runServer);
thread.detach();
asio::错误代码ec;
udpper udpper(&mUDPsock);//忽略此项,它包含字符数组
asio::ip::udp::endpoint ep;
打开(mudpsp.protocol(),ec);
mUDPsock.bind(mUDPep,ec);
while(true)
{
auto dataSize=mUDPsock.receive_from(udpPeer.getReadBuffer(),ep);
如果(ep.address()是_v4())

std::cout您只收听v6

ep
不指示您如何接收

您的v6终结点可以同时接收这两个。打印实际终结点以查看:

#include <boost/asio.hpp>
#include <iostream>
namespace asio = boost::asio;
using asio::ip::udp;

int main() {
    asio::thread_pool context(1);
    udp::socket sock(context, {udp::v6(), 8888});

    udp::endpoint ep;
    char arr[4096];

    while (true) {
        /*auto n =*/ sock.receive_from(asio::buffer(arr), ep);
        std::cout 
            << std::boolalpha << ep.address().is_v4() << " "
            << ep << "\n";
    }

    context.join();
}
印刷品:

false [::1]:49972
false [::ffff:127.0.0.1]:34368
作为比较,说
udp::socket sock(context,{udp::v4(),8888});
根本不接收v6数据包:

true 127.0.0.1:39805
换句话说,由于您的套接字绑定到v6,因此您获得的地址映射为:

if (a.is_v4())
    return asio::ip::address_v6::v4_mapped(a.to_v4());
怎么办? 检查v6是否为v4映射版本或兼容版本:

asio::ip::address_v4 a4;
if (a6.is_v4_compatible() || a6.is_v4_mapped())
    a4 = a6.to_v4();
看起来更现代的界面应该是

 a4 = make_address_v4(asio::ip::v4_mapped, a6);
演示:
asio::ip::address_v4 a4;
if (a6.is_v4_compatible() || a6.is_v4_mapped())
    a4 = a6.to_v4();
 a4 = make_address_v4(asio::ip::v4_mapped, a6);
#include <boost/asio.hpp>
#include <iostream>
namespace asio = boost::asio;
using asio::ip::udp;

int main() {
    asio::thread_pool context(1);
    udp::socket sock(context, {udp::v6(), 8888});

    udp::endpoint ep;
    char arr[4096];

    for (auto n=2; n--;) {
        /*auto n =*/ sock.receive_from(asio::buffer(arr), ep);
        asio::ip::address_v4 a4;

        {
            auto a6 = ep.address().to_v6();
            if (a6.is_v4_compatible() || a6.is_v4_mapped())
                a4 = a6.to_v4();
        }

        std::cout
            << (a4.is_unspecified()? "not-mapped" : a4.to_string()) << " "
            << ep << "\n";
    }

    context.join();
}
127.0.0.1 [::ffff:127.0.0.1]:54859
not-mapped [::1]:36231