boost asio udp套接字连接无效参数(IPv6)
问题描述:
我正在努力解决数小时问题: 我想连接一个boost asio udo套接字到端点。在IPv4中这样做没有问题。但是如果我尝试在IPv6中做同样的事情,我会得到一个错误代码“无效参数”。boost asio udp套接字连接无效参数(IPv6)
using boost::asio::ip::udp;
struct UdpConnectionParams
{
udp::endpoint m_localEndpoint;
udp::endpoint m_remoteEndpoint;
}
boost::system::error_code setupUdpConnection(udp::socket& p_socket, const UdpConnectionParams& p_params)
{
// close socket
boost::system::error_code h_ignoreError;
p_socket.close(h_ignoreError);
// variables for kind of UDP connection
udp h_protocol(udp::v4());
bool h_shallBind{false};
bool h_shallConnect{false};
// determine kind of connection
if(p_params.m_localEndpoint != udp::endpoint())
{
h_protocol = p_params.m_localEndpoint.protocol();
h_shallBind = true;
}
if(p_params.m_remoteEndpoint != udp::endpoint())
{
h_protocol = p_params.m_remoteEndpoint.protocol();
h_shallConnect = true;
}
if(!h_shallBind && !h_shallConnect)
{
// no endpoint specified, return error
return boost::system::error_code(ENetworkErrorCode::NO_ENDPOINT_SPECIFIED, NetworkErrorCategory::getCategory());
}
try
{
p_socket.open(h_protocol);
//bind socket to certain endpoint
if(h_shallBind)
{
p_socket.bind(p_params.m_localEndpoint);
}
//connect socket to client. Thus it is possible to use p_socket.send()
if(h_shallConnect)
{
p_socket.connect(p_params.m_remoteEndpoint);
}
}
catch (boost::system::system_error& h_error)
{
p_socket.close(h_ignoreError);
return h_error.code();
}
// no error
return boost::system::error_code();
}
int main()
{
boost::asio::io_service service;
udp::socket socket(service);
boost::system::error_code error;
UdpConnectionParams params;
params.m_localEndpoint = udp::endpoint(udp::v6(), 55555);
params.m_remoteEndpoint = udp::endpoint(boost::asio::ip::address_v6::from_string("ff01::101"), 55555);
error = setupUdpConnection(socket, params);
cout << error << error.message() << endl; // "invalid argument"
return 0;
}
我没有得到任何错误的唯一方法是使用本地主机IP地址(:: 1)。如果我将套接字绑定到端点,则没有区别。 我在做什么错?
答
我在做什么错?
问题是,您没有在使用的IPv6地址中指定接口索引/范围。 IPv6多播地址需要指定范围,以便网络堆栈将知道您的计算机的哪个本地网络接口将IP地址与之关联。即
代替:
boost::asio::ip::address_v6::from_string("ff01::101"), 55555);
你需要的东西,如:%符号后
boost::asio::ip::address_v6::from_string("ff01::101%eth0"), 55555);
(后缀将取决于您要使用的网络接口的名称,当然)
(注意,“ff01 ::”前缀是针对节点本地IPv6多播组的,这意味着您的UDP数据包只能发送到运行在同一台计算机上的其他程序。你的意图是什么,那么伟大;另一方面,如果你想让你的UDP数据包到达同一局域网中的其他计算机,你需要使用“ff02 ::”或“ff12 ::”前缀(ff02 ::将用于一个知名的,已知的多播地址,ff12 ::将用于临时多播地址)。有关详细信息,请参阅the Wikipedia page上的“组播地址范围”表)
谢谢!那么,我无法使用“ff01 :: 101%eth0”或“ff01 :: 101%lo”,但它可以与“ff12 :: 1%eth0”一起使用。将套接字连接到节点本地IPv6多播组需要什么?如果我不连接套接字,但为什么不使用“send_to”和“receive_from”方法来解决此问题? – Christi258
ff11 :: 1%eth0(或ff11 :: 11%lo等)将是节点本地等效组。至于它为什么与send_to()和receive_from()协同工作,但与connect()不同,我不知道。 –