我有点惊讶这能在同一台机器上工作。我没想到监听端口 1666 的客户端会接收发送到端口 8888 上的广播地址的数据。
bind() http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/basic_datagram_socket/bind/overload1.html assigns a local endpoint (composed of a local address and port) to the socket. When a socket binds to an endpoint, it specifies that the socket will only receive data sent to the bound address and port. It is often advised to bind to address_v4::any() http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/ip__address_v4/any.html, as this will use all available interfaces for listening. In the case of a system with multiple interfaces (possible multiple NIC cards), binding to a specific interface address will result in the socket only listening to data received from the specified interface[1]. Thus, one might find themselves obtaining an address through resolve() http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/reference/ip__basic_resolver/resolve/overload1.html when the application wants to bind to a specific network interface and wants to support resolving it by providing the IP directly (127.0.0.1) or a name (localhost).
需要注意的是,当绑定到套接字时,端点由地址和地址组成。and港口。这就是我惊讶的原因,它可以在同一台机器上运行。如果服务器正在写入广播:8888,则绑定到端口 1666 的套接字不应接收数据报。尽管如此,这里还是端点和网络的可视化:
.--------.
.--------.|
.--------. address: any address: any .--------.||
| | port: any / \ port: 8888 | |||
| server |-( ----------->| address: broadcast |----------> )-| client ||'
| | \ port: 8888 / | |'
'--------' '--------'
服务器绑定到任何地址和任何端口,启用广播选项,并将数据发送到远程端点(广播: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 http://www.wireshark.org/,以验证生存时间 http://en.wikipedia.org/wiki/Time_to_live数据包中的字段足够高,不会在路由过程中被丢弃。
1. On Linux, broadcast datagrams received by an adapter will not be passed to a socket bound to a specific interface, as the datagram's destination is set to the broadcast address. On the other hand, Windows will pass broadcast datagrams received by an adapter to sockets bound to a specific interface.