使用Boost.Asio的广播问题
Issue with broadcast using Boost.Asio
如果这个问题之前已经有人回答过,我先道歉,但我已经搜索过了,没有找到任何帮助我的东西。正如问题的标题所示,我试图将一个包从服务器广播到一组侦听任何消息的客户端。
客户端将计算一秒钟内接收到的消息数。
服务器端是这样的:
class Server
{
public:
Server(boost::asio::io_service& io)
: socket(io, udp::endpoint(udp::v4(), 8888))
, broadcastEndpoint(address_v4::broadcast(), 8888)
, tickHandler(boost::bind(&Server::Tick, this, boost::asio::placeholders::error))
, timer(io, boost::posix_time::milliseconds(20))
{
socket.set_option(boost::asio::socket_base::reuse_address(true));
socket.set_option(boost::asio::socket_base::broadcast(true));
timer.async_wait(tickHandler);
}
private:
void Tick(const boost::system::error_code&)
{
socket.send_to(boost::asio::buffer(buffer), broadcastEndpoint);
timer.expires_at(timer.expires_at() + boost::posix_time::milliseconds(20));
timer.async_wait(tickHandler);
}
private:
udp::socket socket;
udp::endpoint broadcastEndpoint;
boost::function<void(const boost::system::error_code&)> tickHandler;
boost::asio::deadline_timer timer;
boost::array<char, 100> buffer;
};
它被初始化并以如下方式运行:
int main()
{
try
{
boost::asio::io_service io;
Server server(io);
io.run();
}
catch (const std::exception& e)
{
std::cerr << e.what() << "n";
}
return 0;
}
这(显然)工作良好。现在客户端来了…
void HandleReceive(const boost::system::error_code&, std::size_t bytes)
{
std::cout << "Got " << bytes << " bytesn";
}
int main(int argc, char* argv[])
{
if (argc != 2)
{
std::cerr << "Usage: " << argv[0] << " <host>n";
return 1;
}
try
{
boost::asio::io_service io;
udp::resolver resolver(io);
udp::resolver::query query(udp::v4(), argv[1], "1666");
udp::endpoint serverEndpoint = *resolver.resolve(query);
//std::cout << serverEndpoint.address() << "n";
udp::socket socket(io);
socket.open(udp::v4());
socket.bind(serverEndpoint);
udp::endpoint senderEndpoint;
boost::array<char, 300> buffer;
auto counter = 0;
auto start = std::chrono::system_clock::now();
while (true)
{
socket.receive_from(boost::asio::buffer(buffer), senderEndpoint);
++counter;
auto current = std::chrono::system_clock::now();
if (current - start >= std::chrono::seconds(1))
{
std::cout << counter << "n";
counter = 0;
start = current;
}
}
}
catch (const std::exception& e)
{
std::cerr << e.what() << "n";
}
当服务器和客户端在同一台机器上运行时,此操作有效,但当我在不同于运行客户端的机器上运行服务器时,此操作不起作用。
第一件事是,对我来说,我必须解析服务器的地址似乎很奇怪。也许我不知道广播是如何工作的,但我认为服务器会使用打开广播选项的套接字发送消息,并且它会到达同一网络中的所有套接字。
我读到你应该将客户端的套接字绑定到address_v4::any()
地址。我做了,它不工作(说明一个套接字已经使用地址/端口)。
提前感谢。
PS:我用的是Windows 8。
我有点惊讶这在同一台机器上工作。我不会期望监听端口1666的客户端接收到发送到端口8888的广播地址的数据。
bind()
为套接字分配一个本地端点(由本地地址和端口组成)。当套接字绑定到端点时,它指定套接字将只接收发送到绑定地址和端口的数据。通常建议绑定到address_v4::any()
,因为这将使用所有可用的接口进行侦听。在系统有多个接口(可能是多个网卡)的情况下,绑定到特定的接口地址将导致套接字只监听从指定接口[1]接收的数据。因此,当应用程序希望绑定到特定的网络接口并希望通过直接提供IP(127.0.0.1)或名称(localhost)来支持解析它时,可能会发现自己通过resolve()
获得一个地址。
.--------.
.--------.|
.--------. address: any address: any .--------.||
| | port: any / port: 8888 | |||
| server |-( ----------->| address: broadcast |----------> )-| client ||'
| | port: 8888 / | |'
'--------' '--------'
服务器绑定任意地址和任意端口,启用广播选项,并将数据发送到远程端点(broadcast:8888)。绑定到8888端口上任何地址的客户端应该接收到数据。
一个简单的例子如下:
服务器:
#include <boost/asio.hpp>
int main()
{
namespace ip = boost::asio::ip;
boost::asio::io_service io_service;
// Server binds to any address and any port.
ip::udp::socket socket(io_service,
ip::udp::endpoint(ip::udp::v4(), 0));
socket.set_option(boost::asio::socket_base::broadcast(true));
// Broadcast will go to port 8888.
ip::udp::endpoint broadcast_endpoint(ip::address_v4::broadcast(), 8888);
// Broadcast data.
boost::array<char, 4> buffer;
socket.send_to(boost::asio::buffer(buffer), broadcast_endpoint);
}
客户端:#include <iostream>
#include <boost/asio.hpp>
int main()
{
namespace ip = boost::asio::ip;
boost::asio::io_service io_service;
// Client binds to any address on port 8888 (the same port on which
// broadcast data is sent from server).
ip::udp::socket socket(io_service,
ip::udp::endpoint(ip::udp::v4(), 8888 ));
ip::udp::endpoint sender_endpoint;
// Receive data.
boost::array<char, 4> buffer;
std::size_t bytes_transferred =
socket.receive_from(boost::asio::buffer(buffer), sender_endpoint);
std::cout << "got " << bytes_transferred << " bytes." << std::endl;
}
当客户端与服务器不在同一位置时,则可能是各种网络相关问题:
- 验证服务器和客户端之间的连接。
- 检查防火墙异常。
- 在路由设备上验证广播支持/异常。
- 使用网络分析工具(如Wireshark)检查报文中的time to live字段是否足够大,在路由过程中不会被丢弃。
<子> 1。在Linux上,由适配器接收的广播数据报不会传递给绑定到特定接口的套接字,因为数据报的目的地被设置为广播地址。另一方面,Windows将通过适配器接收到的广播数据报传递给绑定到特定接口的套接字。子>
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- setlocale的C++土耳其字符串问题
- 如何重构类层次结构以避免菱形问题
- 基于boost的程序的静态链接——zlib问题
- 使用Boost.Asio的广播问题
- 2路udp广播问题,borland turbo c++