我的目标是使用boost asio在c ++中编写一个小程序,只要在任何网络接口上收到ICMP数据包,就会通知我。
程序不会打印任何错误,也没有例外。
但它也没有收到任何程序发送的任何ICMP数据包,只有一个(可以找到here的升级asio的ping示例。)
更奇怪的是,来自boost示例的ICMP echo请求数据包(相应地调整了有效负载和ICMP标识符之后)和默认的Windows ICMP echo请求(当在windows命令行中使用“ping”时)看起来wireshark几乎完全相同。唯一的区别在于IPv4标头中的标识字段,因此也是ICMP校验和。
无论回应请求来自何处,无论是虚拟机还是网络中的其他真实计算机,都可以观察到相同的行为。 我可以毫无问题地ping所有这些机器。
禁用Windows防火墙会产生相同的结果。
操作系统:Windows 10 64位企业版N(10.0.10586 Build 10586)
提升版本:1.62.0。
IDE:Microsoft Visual Studio社区15.
以下是我提出的建议:
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/icmp.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/placeholders.hpp>
#include <boost/system/error_code.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <iostream>
class ICMPReceiver {
public:
ICMPReceiver( boost::asio::io_service & IOS ):
m_sock( IOS ),
m_localEP( boost::asio::ip::icmp::v4(), 0 )
{
}
bool open() {
boost::system::error_code ec;
if ( !m_sock.is_open() ) {
m_sock.open( boost::asio::ip::icmp::v4(), ec );
if ( ec ) {
std::cerr << "Error in socket.open():\n" << ec.message() << '\n';
return false;
}
}
return true;
}
bool bind() {
boost::system::error_code ec;
m_sock.bind( m_localEP, ec );
if ( ec ) {
std::cerr << "Error in socket.bind():\n" << ec.message() << '\n';
return false;
}
}
bool startReceiving() {
try {
m_sock.async_receive_from( boost::asio::buffer( m_receiveBuffer ),
m_remoteEP,
boost::bind( &ICMPReceiver::receiveHandle,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred ) );
} catch ( std::exception const & e ) {
std::cerr << "Exception in socket.async_receive_from():\n" << e.what() << '\n';
return false;
}
return true;
}
private:
void receiveHandle( boost::system::error_code const & ec, size_t bytes ) {
if ( ec ) {
if ( ec != boost::asio::error::operation_aborted ) {
std::cerr << "Error in receiveHandle():\n" << "Code: " << ec << ": " << ec.message() << '\n';
return;
} else {
std::cerr << "operation aborted\n";
return;
}
} else {
std::cout << "ICMP packet received\n";
}
startReceiving();
}
boost::asio::ip::icmp::socket m_sock;
boost::asio::ip::icmp::endpoint m_localEP;
boost::asio::ip::icmp::endpoint m_remoteEP;
boost::array< char, 2048 > m_receiveBuffer;
};
int main() {
try {
boost::asio::io_service IOS;
ICMPReceiver receiver( IOS );
receiver.open();
receiver.bind();
receiver.startReceiving();
IOS.run();
return 0;
} catch ( std::exception const & e ) {
std::cerr << "Unhandled exception: " << e.what() << '\n';
return 1;
}
}