2016-05-03 13 views
3

例を変更して、複数のホストに対して定期的にpingを実行する方法について、http://www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/example/icmp/ping.cpp のホストを定期的にpingする方法について変更しました。 まず、すべてのホストに対する要求が作成され、ソケットに送信されます。次に、第2段階では、タイマーが終了するまですべての応答が収集されます。Windows上でBoost.Asioを使用する準同時ICMP ping

3つのクライアントの変形例:最初の反復(0)は、最初に受信パケットが常にゼロの長さを有しているが期待どおりたびに動作

// Headers from ping example: 
// http://www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/example/icmp/ 
#include "icmp_header.hpp" 
#include "ipv4_header.hpp" 

#include <boost/asio.hpp> 
#include <iostream> 

using boost::asio::ip::icmp; 
using boost::asio::deadline_timer; 
using boost::asio::io_service; 
using boost::asio::streambuf; 
using boost::system::error_code; 
using std::cout; 
using std::endl; 
namespace posix_time = boost::posix_time; 

static const std::string BODY = "ping"; 
static const auto PROCESS = GetCurrentProcessId(); 

static int gSequence; 
static io_service gService; 
static icmp::socket gSocket(gService, icmp::v4()); 
static deadline_timer gTimer(gService); 
static streambuf gReply; 
static icmp::endpoint gReceiver; 

void StartReceive() 
{ 
    gSocket.async_receive_from(gReply.prepare(65536), gReceiver, 
     [&](const error_code& error, size_t length) 
    { 
     gReply.commit(length); 

     ipv4_header ipv4Hdr; 
     icmp_header icmpHdr; 
     std::string body(BODY.size(), 0); 

     std::istream is(&gReply); 
     is >> ipv4Hdr >> icmpHdr; 
     is.read(&body[0], BODY.size()); 

     auto ip = ipv4Hdr.source_address().to_string(); 
     auto rc = gReceiver.address().to_string(); 
     auto id = icmpHdr.identifier(); 
     auto process = PROCESS; 
     auto sn = icmpHdr.sequence_number(); 
     auto type = icmpHdr.type(); 

     cout << " Length    = " << length << endl; 
     cout << " Error    = " << error << endl; 
     cout << " IP checksum   = " << ipv4Hdr.header_checksum() << endl; 
     cout << " IP address   = " << ip << endl; 
     cout << " Receiver address = " << rc << endl; 
     cout << " ICMP identification = " << id << endl; 
     cout << " ICMP type   = " << (int)type << endl; 
     cout << " Process    = " << process << endl; 
     cout << " Sequence   = " << sn << endl; 

     if (is 
      && icmpHdr.type() == icmp_header::echo_reply 
      && icmpHdr.identifier() == PROCESS 
      && icmpHdr.sequence_number() == gSequence 
      && body == BODY) 
     { 
      cout << " > " << ip << endl; 
     } 

     cout << endl; 

     gReply.consume(length); 

     StartReceive(); 
    }); 
} 

int main() 
{ 
    icmp::resolver resolver(gService); 

    icmp_header echoRequest; 
    echoRequest.type(icmp_header::echo_request); 
    echoRequest.identifier(PROCESS); 

    for (gSequence = 0; gSequence < 3; ++gSequence) 
    { 
     cout << "----------------------------------------------------------" << endl; 
     cout << "Iteration = " << gSequence << endl; 
     cout << "----------------------------------------------------------" << endl; 

     echoRequest.sequence_number(gSequence); 
     compute_checksum(echoRequest, BODY.begin(), BODY.end()); 

     streambuf request; 
     std::ostream os(&request); 
     os << echoRequest << BODY; 

     gService.reset(); 

     StartReceive(); 

     std::vector<std::string> pool 
     { 
      "10.170.110.29", 
      "10.170.97.39", 
      "10.170.7.52" 
     }; 

     for (const auto & ip : pool) 
     { 
      icmp::resolver::query query(icmp::v4(), ip, ""); 
      auto dest = *resolver.resolve(query); 

      gSocket.send_to(request.data(), dest); 
     } 

     gTimer.expires_from_now(posix_time::millisec(2000)); 
     gTimer.async_wait([&](const error_code& error) { gService.stop(); }); 

     gService.run(); 
     gReply.commit(gReply.size()); 
     gReply.consume(gReply.size()); 
    } 

    return 0; 
} 

。ただし、その後のすべての反復では、1つ以上のクライアントからの応答は配信されませんが、別のクライアントからの応答は複数回配信されます。 Wiresharkを使用すると、この例のすべてのホストがリクエストに対して非常に迅速に1つの応答を送信することがわかります。

これは、生産の出力のいずれかです。

---------------------------------------------------------- 
Iteration = 0 
---------------------------------------------------------- 
    Length    = 0 
    Error    = system:10022 
    IP checksum   = 0 
    IP address   = 0.0.0.0 
    Receiver address = 0.0.0.0 
    ICMP identification = 0 
    ICMP type   = 0 
    Process    = 20464 
    Sequence   = 0 

    Length    = 32 
    Error    = system:0 
    IP checksum   = 595 
    IP address   = 10.170.97.39 
    Receiver address = 10.170.97.39 
    ICMP identification = 20464 
    ICMP type   = 0 
    Process    = 20464 
    Sequence   = 0 
    > 10.170.97.39 

    Length    = 32 
    Error    = system:0 
    IP checksum   = 31034 
    IP address   = 10.170.110.29 
    Receiver address = 10.170.110.29 
    ICMP identification = 20464 
    ICMP type   = 0 
    Process    = 20464 
    Sequence   = 0 
    > 10.170.110.29 

    Length    = 32 
    Error    = system:0 
    IP checksum   = 51432 
    IP address   = 10.170.7.52 
    Receiver address = 10.170.7.52 
    ICMP identification = 20464 
    ICMP type   = 0 
    Process    = 20464 
    Sequence   = 0 
    > 10.170.7.52 

---------------------------------------------------------- 
Iteration = 1 
---------------------------------------------------------- 
    Length    = 32 
    Error    = system:0 
    IP checksum   = 594 
    IP address   = 10.170.97.39 
    Receiver address = 10.170.97.39 
    ICMP identification = 20464 
    ICMP type   = 0 
    Process    = 20464 
    Sequence   = 1 
    > 10.170.97.39 

    Length    = 32 
    Error    = system:0 
    IP checksum   = 51419 
    IP address   = 10.170.7.52 
    Receiver address = 10.170.7.52 
    ICMP identification = 20464 
    ICMP type   = 0 
    Process    = 20464 
    Sequence   = 1 
    > 10.170.7.52 

    Length    = 32 
    Error    = system:0 
    IP checksum   = 51419 
    IP address   = 10.170.7.52 
    Receiver address = 10.170.7.52 
    ICMP identification = 20464 
    ICMP type   = 0 
    Process    = 20464 
    Sequence   = 1 
    > 10.170.7.52  

---------------------------------------------------------- 
Iteration = 2 
---------------------------------------------------------- 
    Length    = 32 
    Error    = system:0 
    IP checksum   = 593 
    IP address   = 10.170.97.39 
    Receiver address = 10.170.97.39 
    ICMP identification = 20464 
    ICMP type   = 0 
    Process    = 20464 
    Sequence   = 2 
    > 10.170.97.39 

    Length    = 32 
    Error    = system:0 
    IP checksum   = 51407 
    IP address   = 10.170.7.52 
    Receiver address = 10.170.7.52 
    ICMP identification = 20464 
    ICMP type   = 0 
    Process    = 20464 
    Sequence   = 2 
    > 10.170.7.52 

    Length    = 32 
    Error    = system:0 
    IP checksum   = 51407 
    IP address   = 10.170.7.52 
    Receiver address = 10.170.7.52 
    ICMP identification = 20464 
    ICMP type   = 0 
    Process    = 20464 
    Sequence   = 2 
    > 10.170.7.52 

これはBoost.Asioの正しい使用方法や行動ですか?

ありがとうございました

答えて

1

と思われます。それは私のために働くようです。

注:streambufを使用して

  • がここに過度に複雑ようだ - 私はの1つがものが混乱することができたstreambufの再利用が同じ内容

  • の繰り返し調査結果につながるかどうかを疑問に思いますプールアドレスはローカルのNICアドレスに解決されます(独自のICMPパケットを受信するため)

  • あなたは決して最初の試合を超えたアドレスを解決することはできません。解像度はまったく問題ありませんでした。 (ローカルDNSキャッシュ/ゲートウェイがある場合は特に)、DNS要求もまたあなたの観測を妨げる可能性があります。

    boost::asio::async_resolveを使用することを検討してください。それはタイミングに干渉しないように、おそらくループの外にそれを取っ

    ここ

は簡易版です:。

// Headers from ping example: 
// http://www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/example/icmp/ 
#include "icmp_header.hpp" 
#include "ipv4_header.hpp" 

#include <sys/types.h> 
#include <unistd.h> 
#include <boost/asio.hpp> 
#include <iostream> 
#include <sstream> 

using boost::asio::ip::icmp; 
using boost::asio::deadline_timer; 
using boost::asio::io_service; 
using boost::asio::streambuf; 
using boost::system::error_code; 
using std::cout; 
using std::endl; 
namespace posix_time = boost::posix_time; 

static const std::string BODY = "ping"; 
static const auto PROCESS = getpid(); 

static int gSequence; 
static io_service gService; 
static icmp::socket gSocket(gService, icmp::v4()); 
static char gReply[65536]; 
static icmp::endpoint gReceiver; 

void StartReceive() { 
    gSocket.async_receive_from(boost::asio::buffer(gReply), gReceiver, [&](const error_code &error, size_t length) { 

     ipv4_header ipv4Hdr; 
     icmp_header icmpHdr; 
     std::string body(BODY.size(), 0); 

     std::istringstream is(std::string(gReply, length)); 
     is >> ipv4Hdr >> icmpHdr; 
     is.read(&body[0], BODY.size()); 

     auto ip  = ipv4Hdr.source_address().to_string(); 
     auto rc  = gReceiver.address().to_string(); 
     auto id  = icmpHdr.identifier(); 
     auto process = PROCESS; 
     auto sn  = icmpHdr.sequence_number(); 
     auto type = icmpHdr.type(); 

     cout << " Length="    << length << 
       " Error="    << error << 
       " IP checksum="   << ipv4Hdr.header_checksum() << 
       " IP address="   << ip << 
       " Receiver address=" << rc << 
       " ICMP identification=" << id << 
       " ICMP type="   << (int)type << 
       " Process="    << process << 
       " Sequence="   << sn << "\n"; 

     if (is && icmpHdr.type() == icmp_header::echo_reply && icmpHdr.identifier() == PROCESS && 
      icmpHdr.sequence_number() == gSequence && body == BODY) { 
      cout << " > " << ip << endl; 
     } 

     cout << endl; 

     StartReceive(); 
    }); 
} 

int main() { 
    icmp::resolver resolver(gService); 

    icmp_header echoRequest; 
    echoRequest.type(icmp_header::echo_request); 
    echoRequest.identifier(PROCESS); 

    for (gSequence = 0; gSequence < 3; ++gSequence) { 
     cout << "----------------------------------------------------------" << endl; 
     cout << "Iteration=" << gSequence << endl; 
     cout << "----------------------------------------------------------" << endl; 

     echoRequest.sequence_number(gSequence); 
     compute_checksum(echoRequest, BODY.begin(), BODY.end()); 

     streambuf request; 
     std::ostream os(&request); 
     os << echoRequest << BODY; 

     gService.reset(); 

     StartReceive(); 

     for (std::string ip : { "www.msn.com", "www.google.com" }) { 
      icmp::resolver::query query(icmp::v4(), ip, ""); 
      auto dest = *resolver.resolve(query); 

      gSocket.send_to(request.data(), dest); 
      std::cout << "Sent to " << dest.endpoint() << "\n"; 
     } 

     deadline_timer gTimer(gService); 
     gTimer.expires_from_now(posix_time::millisec(2000)); 
     gTimer.async_wait([&](error_code) { gService.stop(); }); 

     gService.run(); 
    } 
} 

プリント、例えば

---------------------------------------------------------- 
Iteration=0 
---------------------------------------------------------- 
Sent to 204.79.197.203:0 
Sent to 216.58.212.164:0 
Length=32 Error=system:0 IP checksum=49241 IP address=204.79.197.203 Receiver address=204.79.197.203 ICMP identification=8041 ICMP type=0 Process=8041 Sequence=0 
    > 204.79.197.203 

Length=32 Error=system:0 IP checksum=5449 IP address=216.58.212.164 Receiver address=216.58.212.164 ICMP identification=8041 ICMP type=0 Process=8041 Sequence=0 
    > 216.58.212.164 

---------------------------------------------------------- 
Iteration=1 
---------------------------------------------------------- 
Sent to 204.79.197.203:0 
Sent to 216.58.212.164:0 
Length=32 Error=system:0 IP checksum=49240 IP address=204.79.197.203 Receiver address=204.79.197.203 ICMP identification=8041 ICMP type=0 Process=8041 Sequence=1 
    > 204.79.197.203 

Length=32 Error=system:0 IP checksum=5449 IP address=216.58.212.164 Receiver address=216.58.212.164 ICMP identification=8041 ICMP type=0 Process=8041 Sequence=1 
    > 216.58.212.164 

---------------------------------------------------------- 
Iteration=2 
---------------------------------------------------------- 
Sent to 204.79.197.203:0 
Sent to 216.58.212.164:0 
Length=32 Error=system:0 IP checksum=49239 IP address=204.79.197.203 Receiver address=204.79.197.203 ICMP identification=8041 ICMP type=0 Process=8041 Sequence=2 
    > 204.79.197.203 

Length=32 Error=system:0 IP checksum=5449 IP address=216.58.212.164 Receiver address=216.58.212.164 ICMP identification=8041 ICMP type=0 Process=8041 Sequence=2 
    > 216.58.212.164 
関連する問題