简体   繁体   English

使用boost :: asio C ++,LAN上的计算机不能始终接收到255.255.255.255的UDP广播。

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

I am quite new to network programming, but nonetheless I am working on a personal project that requires interfacing between two computers on the LAN. 我对网络编程非常陌生,但是尽管如此,我仍在从事一个个人项目,该项目需要LAN上两台计算机之间的接口。

For all of my networking needs, I am using boost. 对于我所有的网络需求,我都在使用boost。

Since computers running my software on the LAN do not know one another's IP addresses, the program immediately sends a UDP broadcast to 255.255.255.255. 由于在局域网上运行我的软件的计算机不知道彼此的IP地址,因此该程序立即将UDP广播发送到255.255.255.255。 Another computer listens on the port 25566. If a computer receives a broadcast, it replies with another broadcast to ensure that the other connects via a TCP connection in the appropriate manner. 另一台计算机侦听端口25566。如果一台计算机接收到广播,它将以另一广播答复,以确保另一台计算机以适当的方式通过TCP连接进行连接。

I have a laptop, and a desktop, both running Linux. 我有一台笔记本电脑和一台台式机,都运行Linux。 If I test the code (two instances of the same thing) on the same machine, everything works flawlessly. 如果我在同一台机器上测试代码(同一事物的两个实例),那么一切都将完美运行。 However, a problem arises when I run one instance on the laptop, and another on the desktop. 但是,当我在笔记本电脑上运行一个实例,在桌面上运行另一个实例时,就会出现问题。 Two scenarios happen: 发生两种情况:

The first - I run one instance of the program on the Desktop computer. 第一个-我在台式计算机上运行该程序的一个实例。 It sends a "Hello" message to check if another instance is running anywhere else on the LAN. 它发送“ Hello”消息,以检查LAN上其他任何地方是否正在运行另一个实例。 Since there is no other instance running, it receives no response. 由于没有其他实例在运行,因此不会收到任何响应。 Several seconds later, after the desktop instance sets itself up, I start an instance of the program on the laptop. 桌面实例设置好几秒钟后,我在笔记本电脑上启动了该程序的一个实例。 The laptop broadcasts a "Hello" message as well. 笔记本电脑也会广播“ Hello”消息。 However, this is where the problem kicks in. When the laptop is the one sending the "Hello" message, there is only about a 10% chance that the desktop program (already running) actually receives it. 但是,这就是问题所在。当便携式计算机是发送“ Hello”消息的便携式计算机时,桌面程序(已运行)实际上收到它的可能性只有10%。 I monitored the network with Wireshark on the desktop machine, and, again, Wireshark only picks up the broadcast from the laptop 10% of the time. 我使用台式机上的Wireshark监视了网络,再次,Wireshark仅10%的时间从笔记本电脑中接收广播。 However, if I run Wireshark on the laptop that is sending the "Hello" broadcast, Wireshark picks it up every single time. 但是,如果我在发送“ Hello”广播的笔记本电脑上运行Wireshark,则Wireshark每次都会拾取它。

The second - This is similar to the first, except the laptop runs the program first. 第二个-与第一个类似,除了笔记本电脑先运行程序。 I then start the desktop instance several seconds later. 然后几秒钟后,我启动桌面实例。 However, when the desktop broadcasts "Hello" the laptop receives the broadcast about 95% of the time (in contrast to 10% of the time when the roles are reversed). 但是,当台式机广播“ Hello”时,笔记本电脑大约有95%的时间接收到广播(相反,角色反转的时间为10%)。 The laptop then responds with a "Configure" broadcast. 然后,笔记本电脑将以“配置”广播进行响应。 The desktop then receives the "Configure" broadcast nearly 100% of the time. 然后,台式机几乎100%的时间都会收到“配置”广播。 I confirmed the 95% receive rate with Wireshark again. 我再次与Wireshark确认了95%的接收率。

I am certain there is no problem with my program ignoring these packets. 我敢肯定我的程序忽略这些数据包没有问题。 However, something is happening in the network where the broadcast packets are ignored or filtered. 但是,在广播包被忽略或过滤的网络中发生了一些事情。 What I find particularly strange is how the desktop program only receives the "Hello" message 10% of the time in scenario 1, but receives the "Configure" message 100% of the time in scenario 2. If something strange was happening that prevented packets from reaching the desktop, woulden't both of those percentages be roughly equal? 我发现特别奇怪的是,在方案1中,桌面程序如何仅在10%的时间内收到“ Hello”消息,而在方案2中100%的时间内仅收到“ Configure”消息。从到达桌面后,这两个百分比是否大致相等?

Here is some of the code that I run to setup the necessary sockets: 这是我用来设置必要的套接字的一些代码:

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)

Here is the code I use to receive broadcasted messages: 这是我用来接收广播消息的代码:

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
}

And finally, here is how I send data: 最后,这是我发送数据的方式:

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

So essentially my question is, why does some of my broadcasts not get through? 所以本质上我的问题是,为什么我的某些广播无法播放?

Thanks 谢谢

EDIT: 编辑:

Also, I forgot to mention that each computer receives its OWN broadcast every single time. 另外,我忘了提到每台计算机每次都收到其OWN广播。 So I think its a problem with the network, and not my code. 因此,我认为这是网络问题,而不是我的代码问题。

UDP is not guaranteed to deliver. 不能保证UDP传递。 That's part of the properties of the protocol. 这是协议属性的一部分。

The fact that you can observe the behaviour with Wireshark confirms that it has little to do with Boost. 您可以使用Wireshark观察行为的事实证实,它与Boost无关。

Using 255.255.255.255 is a blunt weapon and it is limited: 使用255.255.255.255是一种钝器,并且受到限制:

Setting all the bits of an IP address to one, or 255.255.255.255, forms the limited broadcast address. 将IP地址的所有位设置为1或255.255.255.255,将形成受限的广播地址。 Sending a UDP datagram to this address delivers the message to any host on the local network segment. 将UDP数据报发送到此地址会将消息传递到本地网段上的任何主机。 Because routers never forward messages sent to this address, only hosts on the network segment receive the broadcast message. 由于路由器从不转发发送到该地址的消息,因此只有网段上的主机才能收到广播消息。

You can be more targeted by using the subnet mask: 使用子网掩码可以使您更具针对性:

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. 例如,要将广播发送到以192.168.1开头的IP地址标识的网络上的所有主机,请使用地址192.168.1.255。

This heightens the chance that the router will know where to send the packet (I'm not a network engineer, so I'm not sure about the implementation details). 这增加了路由器知道将数据包发送到哪里的机会(我不是网络工程师,所以我不确定实现细节)。

Enter Multicast Groups : 输入多播组

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). 组的成员资格是动态的,并由接收者控制(依次由本地客户端应用程序通知)。

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

This is more likely to fit your application. 这更有可能适合您的应用程序。 You'll have to select a good group endpoint depending on the network configuration, so it's slightly more involved. 您必须根据网络配置选择一个合适的组终结点,所以它的参与度稍高一些。

Yet, you'll have support of all modern router hardware/software to ensure delivery to the interested parties (only). 但是,您将获得所有现代路由器硬件/软件的支持,以确保(仅)交付给相关方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM