使用boost asio获取任何收到的ICMP数据包的副本

时间:2017-01-20 12:59:00

标签: c++ network-programming boost-asio icmp raw-sockets

我的目标是使用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;
    }
}

0 个答案:

没有答案