繁体   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++

我对网络编程非常陌生,但是尽管如此,我仍在从事一个个人项目,该项目需要LAN上两台计算机之间的接口。

对于我所有的网络需求,我都在使用boost。

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

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

第一个-我在台式计算机上运行该程序的一个实例。 它发送“ Hello”消息,以检查LAN上其他任何地方是否正在运行另一个实例。 由于没有其他实例在运行,因此不会收到任何响应。 桌面实例设置好几秒钟后,我在笔记本电脑上启动了该程序的一个实例。 笔记本电脑也会广播“ Hello”消息。 但是,这就是问题所在。当便携式计算机是发送“ Hello”消息的便携式计算机时,桌面程序(已运行)实际上收到它的可能性只有10%。 我使用台式机上的Wireshark监视了网络,再次,Wireshark仅10%的时间从笔记本电脑中接收广播。 但是,如果我在发送“ Hello”广播的笔记本电脑上运行Wireshark,则Wireshark每次都会拾取它。

第二个-与第一个类似,除了笔记本电脑先运行程序。 然后几秒钟后,我启动桌面实例。 但是,当台式机广播“ Hello”时,笔记本电脑大约有95%的时间接收到广播(相反,角色反转的时间为10%)。 然后,笔记本电脑将以“配置”广播进行响应。 然后,台式机几乎100%的时间都会收到“配置”广播。 我再次与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是一种钝器,并且受到限制:

将IP地址的所有位设置为1或255.255.255.255,将形成受限的广播地址。 将UDP数据报发送到此地址会将消息传递到本地网段上的任何主机。 由于路由器从不转发发送到该地址的消息,因此只有网段上的主机才能收到广播消息。

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

通过设置主机标识符的所有位,可以将广播定向到网络的特定部分。 例如,要将广播发送到以192.168.1开头的IP地址标识的网络上的所有主机,请使用地址192.168.1.255。

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

输入多播组

与广播传输(某些局域网中使用的广播传输)不同,多播客户端仅在事先选择这样做(通过加入特定的多播组地址)时才接收数据包流。 组的成员资格是动态的,并由接收者控制(依次由本地客户端应用程序通知)。

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

这更有可能适合您的应用程序。 您必须根据网络配置选择一个合适的组终结点,所以它的参与度稍高一些。

但是,您将获得所有现代路由器硬件/软件的支持,以确保(仅)交付给相关方。

暂无
暂无

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

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