LAN 上的计算机使用 boost::asio C++ 无法持续​​接收到 255.255.255.255 的 UDP 广播

Computers on LAN do not consistently receive a UDP broadcast to 255.255.255.255 using boost::asio C++

我对网络编程还很陌生,但我正在从事一个个人项目,该项目需要在 LAN 上的两台计算机之间进行连接。

为了满足我所有的网络需求,我正在使用 boost。

由于在 LAN 上安装我的软件的计算机 运行 不知道彼此的 IP 地址,程序会立即向 255.255.255.255 发送一个 UDP 广播。另一台计算机在端口 25566 上侦听。如果一台计算机收到广播,它会回复另一个广播,以确保另一台计算机以适当的方式通过 TCP 连接进行连接。

我有一台笔记本电脑和一台台式机,都 运行宁 Linux。如果我在同一台机器上测试代码(同一事物的两个实例),一切都会完美无缺。但是,当我 运行 一个实例在笔记本电脑上,另一个实例在台式机上时,问题就出现了。发生两种情况:

第一个 - 我 运行 桌面计算机上程序的一个实例。它发送一条 "Hello" 消息来检查是否有另一个实例正在 运行ning 局域网上的其他任何地方。由于没有其他实例运行ning,它没有收到任何响应。几秒钟后,在桌面实例自行设置后,我在笔记本电脑上启动了该程序的一个实例。笔记本电脑也会广播 "Hello" 消息。然而,这就是问题所在。当笔记本电脑发送 "Hello" 消息时,桌面程序(已经 运行ning)实际收到它的可能性只有 10%。我在台式机上使用 Wireshark 监控网络,同样,Wireshark 仅在 10% 的时间内从笔记本电脑接收广播。但是,如果我在发送 "Hello" 广播的笔记本电脑上 运行 Wireshark,Wireshark 每次都会接收它。

第二个 - 这与第一个类似,除了笔记本电脑 运行 首先是程序。然后我在几秒钟后启动桌面实例。但是,当台式机广播 "Hello" 时,笔记本电脑大约有 95% 的时间接收到广播(相反,当角色互换时只有 10% 的时间)。然后膝上型计算机以 "Configure" 广播响应。然后桌面几乎 100% 的时间接收到 "Configure" 广播。我再次用Wireshark确认了95%的接收率

我确定我的程序忽略这些数据包没有问题。但是,网络中发生了一些事情,广播数据包被忽略或过滤掉了。我发现特别奇怪的是,桌面程序如何在场景 1 中仅在 10% 的时间内接收到 "Hello" 消息,但在场景 2 中却在 100% 的时间内接收到 "Configure" 消息。如果出现奇怪的情况发生阻止数据包到达桌面的情况,这两个百分比不会大致相等吗?

这是我 运行 设置必要套接字的一些代码:

broadcast_socket = new udp::socket(*ioservice); //Set up the socket that broadcasts the message
listen_socket = new udp::socket(*ioservice); //Set up the socket on port 25565 that listens for a broadcast

//Set up the ioservice...

error_code e1, e2;
broadcast_socket->open(udp::v4(), e1); //Actually open the sockets
listen_socket->open(udp::v4(), e2);

//Do some error code checking...

listen_endpoint = udp::endpoint(ip::address_v4::any(), port); //Get endpoint for port 25566 (listen_endpoint becomes 0.0.0.0:25566 after this call)

listen_socket->set_option(udp::socket::reuse_address(true));
listen_socket->bind(listen_endpoint);

broadcast_socket->set_option(udp::socket::reuse_address(true));
broadcast_socket->set_option(socket_base::broadcast(true));

broadcast_endpoint = udp::endpoint(ip::address_v4::broadcast(), port); //Get the broadcast_endpoint (returns 255.255.255.255)

这是我用来接收广播消息的代码:

error_code ec;
size_t available_bytes = listen_socket->available(ec); //See if data is available
size_t read_bytes = 0;
char buffer[1024];

if(available_bytes > 0 && !ec){
    read_bytes = listen_socket->receive_from(boost::asio::buffer(buffer, (available_bytes < sizeof(buffer) ? available_bytes : sizeof(buffer))), listen_endpoint);

    read_data.append(buffer, read_bytes); //Append to a string for later processing
}

最后,这是我发送数据的方式:

std::string payload = "Some payload stuff goes here";

broadcast_socket->send_to(boost::asio::buffer(payload, payload.size()), broadcast_endpoint); //Broadcasts to the broadcast_endpoint (255.255.255.255) which was determined earlier

所以基本上我的问题是,为什么我的一些广播没有通过?

谢谢

编辑:

此外,我忘了提到每台计算机每次都会收到自己的 OWN 广播。所以我认为这是网络问题,而不是我的代码。

不保证 UDP 传送。这是协议属性的一部分。

您可以使用 Wireshark 观察行为这一事实证实它与 Boost 几乎没有关系。

使用255.255.255.255是一把钝器而且有限制:

Setting all the bits of an IP address to one, or 255.255.255.255, forms the limited broadcast address. Sending a UDP datagram to this address delivers the message to any host on the local network segment. Because routers never forward messages sent to this address, only hosts on the network segment receive the broadcast message.

您可以使用子网掩码更有针对性:

Broadcasts can be directed to specific portions of a network by setting all bits of the host identifier. For example, to send a broadcast to all hosts on the network identified by IP addresses starting with 192.168.1, use the address 192.168.1.255.

这增加了路由器知道将数据包发送到哪里的机会(我不是网络工程师,所以我不确定实现细节)。

输入多播组:

Unlike broadcast transmission (which is used on some local area networks), multicast clients receive a stream of packets only if they have previously elect to do so (by joining the specific multicast group address). Membership of a group is dynamic and controlled by the receivers (in turn informed by the local client applications).

(来源:http://www.erg.abdn.ac.uk/users/gorry/course/intro-pages/uni-b-mcast.html

这更有可能适合您的申请。根据网络配置,您必须 select 一个好的组端点,所以它稍微复杂一些。

然而,您将获得所有现代路由器的支持 hardware/software 以确保交付给感兴趣的各方(仅)。