]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/example/cpp03/icmp/ping.cpp
5 // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #include <boost/asio.hpp>
12 #include <boost/bind.hpp>
17 #include "icmp_header.hpp"
18 #include "ipv4_header.hpp"
20 using boost::asio::ip::icmp
;
21 using boost::asio::deadline_timer
;
22 namespace posix_time
= boost::posix_time
;
27 pinger(boost::asio::io_context
& io_context
, const char* destination
)
28 : resolver_(io_context
), socket_(io_context
, icmp::v4()),
29 timer_(io_context
), sequence_number_(0), num_replies_(0)
31 destination_
= *resolver_
.resolve(icmp::v4(), destination
, "").begin();
40 std::string
body("\"Hello!\" from Asio ping.");
42 // Create an ICMP header for an echo request.
43 icmp_header echo_request
;
44 echo_request
.type(icmp_header::echo_request
);
46 echo_request
.identifier(get_identifier());
47 echo_request
.sequence_number(++sequence_number_
);
48 compute_checksum(echo_request
, body
.begin(), body
.end());
50 // Encode the request packet.
51 boost::asio::streambuf request_buffer
;
52 std::ostream
os(&request_buffer
);
53 os
<< echo_request
<< body
;
56 time_sent_
= posix_time::microsec_clock::universal_time();
57 socket_
.send_to(request_buffer
.data(), destination_
);
59 // Wait up to five seconds for a reply.
61 timer_
.expires_at(time_sent_
+ posix_time::seconds(5));
62 timer_
.async_wait(boost::bind(&pinger::handle_timeout
, this));
67 if (num_replies_
== 0)
68 std::cout
<< "Request timed out" << std::endl
;
70 // Requests must be sent no less than one second apart.
71 timer_
.expires_at(time_sent_
+ posix_time::seconds(1));
72 timer_
.async_wait(boost::bind(&pinger::start_send
, this));
77 // Discard any data already in the buffer.
78 reply_buffer_
.consume(reply_buffer_
.size());
80 // Wait for a reply. We prepare the buffer to receive up to 64KB.
81 socket_
.async_receive(reply_buffer_
.prepare(65536),
82 boost::bind(&pinger::handle_receive
, this, _2
));
85 void handle_receive(std::size_t length
)
87 // The actual number of bytes received is committed to the buffer so that we
88 // can extract it using a std::istream object.
89 reply_buffer_
.commit(length
);
91 // Decode the reply packet.
92 std::istream
is(&reply_buffer_
);
95 is
>> ipv4_hdr
>> icmp_hdr
;
97 // We can receive all ICMP packets received by the host, so we need to
98 // filter out only the echo replies that match the our identifier and
99 // expected sequence number.
100 if (is
&& icmp_hdr
.type() == icmp_header::echo_reply
101 && icmp_hdr
.identifier() == get_identifier()
102 && icmp_hdr
.sequence_number() == sequence_number_
)
104 // If this is the first reply, interrupt the five second timeout.
105 if (num_replies_
++ == 0)
108 // Print out some information about the reply packet.
109 posix_time::ptime now
= posix_time::microsec_clock::universal_time();
110 std::cout
<< length
- ipv4_hdr
.header_length()
111 << " bytes from " << ipv4_hdr
.source_address()
112 << ": icmp_seq=" << icmp_hdr
.sequence_number()
113 << ", ttl=" << ipv4_hdr
.time_to_live()
114 << ", time=" << (now
- time_sent_
).total_milliseconds() << " ms"
121 static unsigned short get_identifier()
123 #if defined(BOOST_ASIO_WINDOWS)
124 return static_cast<unsigned short>(::GetCurrentProcessId());
126 return static_cast<unsigned short>(::getpid());
130 icmp::resolver resolver_
;
131 icmp::endpoint destination_
;
132 icmp::socket socket_
;
133 deadline_timer timer_
;
134 unsigned short sequence_number_
;
135 posix_time::ptime time_sent_
;
136 boost::asio::streambuf reply_buffer_
;
137 std::size_t num_replies_
;
140 int main(int argc
, char* argv
[])
146 std::cerr
<< "Usage: ping <host>" << std::endl
;
147 #if !defined(BOOST_ASIO_WINDOWS)
148 std::cerr
<< "(You may need to run this program as root.)" << std::endl
;
153 boost::asio::io_context io_context
;
154 pinger
p(io_context
, argv
[1]);
157 catch (std::exception
& e
)
159 std::cerr
<< "Exception: " << e
.what() << std::endl
;