我正在开发一个侦听多个 UDP 端口的 C++ 程序,并且需要检索接收到的数据包的 TTL。Boost ASIO 不提供对此的访问。
我使用boost raw sockets而不是udp sockets向程序添加了raw sockets。经过一番努力,我能够发送和接收设置自己 IP 和 UDP 标头的 UDP 数据包。
问题是程序在每个套接字上接收的重复数据包与创建的套接字数量一样多。如果我打开 3 个套接字,我每个接收 3 个数据包,打开 4 个接收 4... Wireshark 向我显示网络上的一切都很好。
这是我启动套接字的方式:
sockstr_.sin_family = AF_INET;
sockstr_.sin_port = htons(localendpoint.port());
sockstr_.sin_addr.s_addr = inet_addr(localendpoint.address().to_string().c_str());
socklen_t socklen = (socklen_t) sizeof(sockstr_);
if ((raw_socket_ = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) {
throw std::runtime_error("Failed to open socket! ");
}
int on = 1;
setsockopt(raw_socket_, IPPROTO_IP, IP_HDRINCL , &on, sizeof(on));
if (bind(raw_socket_, (struct sockaddr*) &sockstr_, socklen) == -1) {
close(raw_socket_);
throw std::runtime_error("Failed to bind socket! ");
}
// udp_socket_ defined in header file
// boost::asio::ip::raw_udp::socket udp_socket_;
udp_socket_.assign(boost::asio::ip::raw_udp::v4(), raw_socket_);
// Then I simply use boost functions
udp_socket_.async_send_to(boost::asio::buffer(ST), ref_endpoint_ ...
udp_socket_.async_receive_from(boost::asio::buffer(RT), ref_endpoint_ ...
在日志中,我看到所有原始套接字共享相同的端口号 17,但我的程序在我选择的端口上发送和接收,wireshark 向我显示了这一点。我想这就是问题的根源。知道如何更改原始套接字端口吗?或解决问题的其他解决方案:
[10:06:09.966254][0014][debug]: Socket : 11
[10:06:09.966301][0015][debug]: UDP Source endpoint: 10.20.100.121:17
[10:06:09.966347][0016][debug]: Client [0] starting test session [0] with endless duration !
[10:06:09.966652][0017][debug]: Socket : 12
[10:06:09.966696][0018][debug]: UDP Source endpoint: 10.20.100.121:17
[10:06:09.966731][0019][debug]: Client [0] starting test session [1] with endless duration !
[10:06:09.967040][001a][debug]: Socket : 13
[10:06:09.967078][001b][debug]: UDP Source endpoint: 10.20.100.121:17
[10:06:09.967112][001c][debug]: Client [0] starting test session [2] with endless duration !
这是 raw_udp 代码:
namespace boost {
namespace asio {
namespace ip {
class raw_udp
{
public:
typedef basic_endpoint<raw_udp> endpoint;
static raw_udp v4()
{
return raw_udp(IPPROTO_UDP, AF_INET);
}
static raw_udp v6()
{
return raw_udp(IPPROTO_UDP, AF_INET);
}
int type() const
{
return SOCK_RAW;
}
int protocol() const
{
return protocol_;
}
int family() const
{
return family_;
}
typedef basic_raw_socket<raw_udp> socket;
typedef basic_resolver<raw_udp> resolver;
friend bool operator==(const raw_udp& p1, const raw_udp& p2)
{
return p1.protocol_ == p2.protocol_ && p1.family_ == p2.family_;
}
friend bool operator!=(const raw_udp& p1, const raw_udp& p2)
{
return p1.protocol_ != p2.protocol_ || p1.family_ != p2.family_;
}
private:
explicit raw_udp(int protocol_id, int protocol_family)
: protocol_(protocol_id),
family_(protocol_family)
{
}
int protocol_;
int family_;
};
} // namespace ip
} // namespace asio
} // namespace boost