Networking 让两个UDP服务器在同一端口上侦听?

Networking 让两个UDP服务器在同一端口上侦听?,networking,network-programming,udp,Networking,Network Programming,Udp,我有一个客户端,它通过UDP广播发送数据。(比如说127.0.0.255:12345) 现在我想让多个服务器监听这些数据。要在本地计算机上执行此操作,他们需要共享端口12345以进行侦听 我的问题是,如果可能的话,这种方法是否有缺点,是否有问题 不幸的是,有一种选择会带来大量开销: 实施某种注册流程。启动时,每台服务器都会告诉客户机其端口。然后,客户端将消息发送到每个端口(必须多次发送数据,需要实现某种握手… 你知道更好的选择吗 如果这很重要: 我用C++与Boosi::Asio。软件应该是可移

我有一个客户端,它通过UDP广播发送数据。(比如说127.0.0.255:12345)

现在我想让多个服务器监听这些数据。要在本地计算机上执行此操作,他们需要共享端口12345以进行侦听

我的问题是,如果可能的话,这种方法是否有缺点,是否有问题

不幸的是,有一种选择会带来大量开销:
实施某种注册流程。启动时,每台服务器都会告诉客户机其端口。然后,客户端将消息发送到每个端口(必须多次发送数据,需要实现某种握手…
你知道更好的选择吗

如果这很重要:

我用C++与Boosi::Asio。软件应该是可移植的(主要是Linux和Windows)。

您必须在这两个进程中使用SO_REUSEPORT选项绑定套接字。如果在第一个进程中未指定此选项,则第二个进程中的绑定将失败。同样,如果在第一个选项中指定此选项,而不是在第二个选项中指定此选项,则第二个选项中的绑定将失败。该选项有效地指定了一个请求(“我想绑定到此端口,即使它已经被另一个进程绑定了”)和一个权限(“其他进程也可能绑定到此端口”)


有关更多信息,请参见的第4.12节。

此答案参考了cdhowie的答案,他链接了一份文件,其中说明SO_REUSEPORT将具有我试图实现的效果

我研究了这个选项是如何实现的,以及是否实现的,主要关注Boost::Asio和Linux

只有当OS等于BSD或MacOSX时,Asio才会设置此选项。该代码包含在文件
boost/asio/detail/reactive\u socket\u service.hpp
(boost版本1.40,在较新版本中,该代码已移动到其他文件中)。
我想知道为什么Asio没有为Linux和Windows等平台定义此选项

有几篇参考文献讨论了Linux中没有实现这一点:

还有一个补丁应该将此功能添加到内核:

我不知道Windows是否存在此选项,但通过将
portable
定义为在Linux上运行的软件的属性,这意味着,SO_REUSEPORT是特定于操作系统的,对于我的问题没有可移植的解决方案

在我链接的其中一个讨论中,建议UDP实现一个主侦听器,然后将传入的数据提供给多个从侦听器


我会将这个答案标记为已接受(虽然接受我自己的答案感觉有点糟糕),因为它指出了为什么在便携式软件中使用SO_REUSEPORT的方法会失败。

一些来源解释说,您应该在windows上使用SO_ReuseAdr。但是没有人提到可以在绑定套接字和不绑定套接字的情况下接收UDP消息。 下面的代码将套接字绑定到一个本地listen_端点,这很重要,因为如果没有它,您可以并且仍然会接收UDP消息,但默认情况下,您将拥有端口的独占所有权

但是,如果您在套接字上(或在使用TCP时在接受程序上)设置reuse_address(true),然后绑定套接字,则会使多个应用程序或您自己的应用程序的多个实例再次执行此操作,并且每个人都将收到所有消息

// Create the socket so that multiple may be bound to the same address.
boost::asio::ip::udp::endpoint listen_endpoint(
    listen_address, multicast_port);

// == important part ==
socket_.open(listen_endpoint.protocol());
socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
socket_.bind(listen_endpoint);
// == important part ==

boost::array<char, 2000> recvBuffer;
socket_.async_receive_from(boost::asio::buffer(recvBuffer), m_remote_endpoint,
        boost::bind(&SocketReader::ReceiveUDPMessage, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)
//创建套接字,以便将多个套接字绑定到同一地址。
boost::asio::ip::udp::端点侦听\U端点(
侦听地址、多播端口);
//==重要部分==
socket_u.open(listen_endpoint.protocol());
套接字\设置\选项(boost::asio::ip::udp::socket::重用\地址(true));
套接字绑定(侦听端点);
//==重要部分==
boost::数组recvBuffer;
套接字异步接收来自(boost::asio::buffer(recvBuffer),m_远程端点,
boost::bind(&SocketReader::ReceiveUDPMessage,this,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transfer)

我尝试使用boost::asio::udp::socket
set_option(udp::socket::reuse_address(true));
但没有成功…几乎没有关于这方面的文档,有人对此有什么提示吗?另请参阅我将此答案标记为“正确”因为它表明不可能同时在服务器的1个端口上侦听。链接的url支持此答案。如果发布了另一个答案,表明这是可能的,或者有更详细的解释,我会将新答案标记为已接受,而不是此。@MOnsDaR:什么意思是“不可能”来自该文档:“如果所有进程都使用SO_REUSEPORT选项,那么SO_REUSEPORT标志允许多个进程绑定到同一地址。”它没有显示任何类似的内容。它显示了这是可能的,并且说明了如何实现。我可能在Boost::Asio中遇到了问题。似乎没有添加REUSEPORT,也不可能激活它。很抱歉,我感到困惑,根据文档,这应该是可能的。当然,从那时起,Linux获得了添加的功能(从内核3.9开始)。请参见此处有趣的信息:——然而,
SO_REUSEPORT
意味着多个服务器可以接受数据报,而不是它们都接收相同的数据报。