ping.cpp
Go to the documentation of this file.
1 //
2 // ping.cpp
3 // ~~~~~~~~
4 //
5 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #include <boost/asio.hpp>
12 #include <boost/bind.hpp>
13 #include <istream>
14 #include <iostream>
15 #include <ostream>
16 
17 #include "icmp_header.hpp"
18 #include "ipv4_header.hpp"
19 
20 using boost::asio::ip::icmp;
21 using boost::asio::deadline_timer;
22 namespace posix_time = boost::posix_time;
23 
24 class pinger
25 {
26 public:
27  pinger(boost::asio::io_service& io_service, const char* destination)
28  : resolver_(io_service), socket_(io_service, icmp::v4()),
29  timer_(io_service), sequence_number_(0), num_replies_(0)
30  {
31  icmp::resolver::query query(icmp::v4(), destination, "");
32  destination_ = *resolver_.resolve(query);
33 
34  start_send();
35  start_receive();
36  }
37 
38  double delay;
39 
40 private:
41  void start_send()
42  {
43  std::string body("\"Hello!\" from Asio ping.");
44 
45  // Create an ICMP header for an echo request.
46  icmp_header echo_request;
47  echo_request.type(icmp_header::echo_request);
48  echo_request.code(0);
49  echo_request.identifier(get_identifier());
50  echo_request.sequence_number(++sequence_number_);
51  compute_checksum(echo_request, body.begin(), body.end());
52 
53  // Encode the request packet.
54  boost::asio::streambuf request_buffer;
55  std::ostream os(&request_buffer);
56  os << echo_request << body;
57 
58  // Send the request.
59  time_sent_ = posix_time::microsec_clock::universal_time();
60  socket_.send_to(request_buffer.data(), destination_);
61 
62  // Wait up to five seconds for a reply.
63  num_replies_ = 0;
64  timer_.expires_at(time_sent_ + posix_time::seconds(5));
65  timer_.async_wait(boost::bind(&pinger::handle_timeout, this));
66  }
67 
69  {
70  if (num_replies_ == 0) {
71  std::cout << "Request timed out" << std::endl;
72  delay = -1;
73  }
74 
75  // Requests must be sent no less than one second apart.
76  timer_.expires_at(time_sent_ + posix_time::seconds(1));
77  timer_.async_wait(boost::bind(&pinger::start_send, this));
78 
79  }
80 
82  {
83  // Discard any data already in the buffer.
84  reply_buffer_.consume(reply_buffer_.size());
85 
86  // Wait for a reply. We prepare the buffer to receive up to 64KB.
87  socket_.async_receive(reply_buffer_.prepare(65536),
88  boost::bind(&pinger::handle_receive, this, _2));
89  }
90 
91  void handle_receive(std::size_t length)
92  {
93  // The actual number of bytes received is committed to the buffer so that we
94  // can extract it using a std::istream object.
95  reply_buffer_.commit(length);
96 
97  // Decode the reply packet.
98  std::istream is(&reply_buffer_);
99  ipv4_header ipv4_hdr;
100  icmp_header icmp_hdr;
101  is >> ipv4_hdr >> icmp_hdr;
102 
103  // We can receive all ICMP packets received by the host, so we need to
104  // filter out only the echo replies that match the our identifier and
105  // expected sequence number.
106  if (is && icmp_hdr.type() == icmp_header::echo_reply
107  && icmp_hdr.identifier() == get_identifier()
108  && icmp_hdr.sequence_number() == sequence_number_)
109  {
110  // If this is the first reply, interrupt the five second timeout.
111  if (num_replies_++ == 0)
112  timer_.cancel();
113 
114  // Print out some information about the reply packet.
115  posix_time::ptime now = posix_time::microsec_clock::universal_time();
116  delay = (now - time_sent_).total_nanoseconds()/(1000.0*1000); // added
117  std::cout << length - ipv4_hdr.header_length()
118  << " bytes from " << ipv4_hdr.source_address()
119  << ": icmp_seq=" << icmp_hdr.sequence_number()
120  << ", ttl=" << ipv4_hdr.time_to_live()
121  //<< ", time=" << (now - time_sent_).total_milliseconds() << " ms"
122  << ", time=" << delay << " ms"
123  << std::endl;
124  }
125 
126  start_receive();
127  }
128 
129  static unsigned short get_identifier()
130  {
131 #if defined(BOOST_WINDOWS)
132  return static_cast<unsigned short>(::GetCurrentProcessId());
133 #else
134  return static_cast<unsigned short>(::getpid());
135 #endif
136  }
137 
138  icmp::resolver resolver_;
139  icmp::endpoint destination_;
140  icmp::socket socket_;
141  deadline_timer timer_;
142  unsigned short sequence_number_;
143  posix_time::ptime time_sent_;
144  boost::asio::streambuf reply_buffer_;
145  std::size_t num_replies_;
146 };
147 
148 #if 0
149 int main(int argc, char* argv[])
150 {
151  try
152  {
153  if (argc != 2)
154  {
155  std::cerr << "Usage: ping <host>" << std::endl;
156 #if !defined(BOOST_WINDOWS)
157  std::cerr << "(You may need to run this program as root.)" << std::endl;
158 #endif
159  return 1;
160  }
161 
162  boost::asio::io_service io_service;
163  pinger p(io_service, argv[1]);
164  io_service.run();
165  }
166  catch (std::exception& e)
167  {
168  std::cerr << "Exception: " << e.what() << std::endl;
169  }
170 }
171 #endif
Definition: ping.cpp:24
void handle_receive(std::size_t length)
Definition: ping.cpp:91
unsigned short header_length() const
Definition: ipv4_header.hpp:57
void handle_timeout()
Definition: ping.cpp:68
static unsigned short get_identifier()
Definition: ping.cpp:129
boost::asio::streambuf reply_buffer_
Definition: ping.cpp:144
posix_time::ptime time_sent_
Definition: ping.cpp:143
unsigned short sequence_number_
Definition: ping.cpp:142
unsigned int time_to_live() const
Definition: ipv4_header.hpp:64
icmp::socket socket_
Definition: ping.cpp:140
double delay
Definition: ping.cpp:38
void compute_checksum(icmp_header &header, Iterator body_begin, Iterator body_end)
Definition: icmp_header.hpp:75
icmp::endpoint destination_
Definition: ping.cpp:139
boost::asio::ip::address_v4 source_address() const
Definition: ipv4_header.hpp:68
icmp::resolver resolver_
Definition: ping.cpp:138
pinger(boost::asio::io_service &io_service, const char *destination)
Definition: ping.cpp:27
unsigned short identifier() const
Definition: icmp_header.hpp:46
deadline_timer timer_
Definition: ping.cpp:141
unsigned char type() const
Definition: icmp_header.hpp:43
unsigned short sequence_number() const
Definition: icmp_header.hpp:47
void start_send()
Definition: ping.cpp:41
unsigned char code() const
Definition: icmp_header.hpp:44
void start_receive()
Definition: ping.cpp:81
std::size_t num_replies_
Definition: ping.cpp:145
int main(int argc, char *argv[])
Definition: rosping.cpp:7


rosping
Author(s): Kei Okada
autogenerated on Tue May 11 2021 02:55:50