For your convenience, I wrote a simple NTP client using nothing but standard C++ and the boost::asio library. The code for it is attached below. Using the static method NtpClient::GetTime(), the current time as reported by pool.ntp.org is retreaved as in the following program:
#include <iostream>
#include "NtpClient.hpp"
#include <boost/date_time/posix_time/posix_time.hpp> // Need I/O.
int main(int argc,char** argv)
{
if( 1 == argc )
{
std::cout << NtpClient::GetTime() << '\n';
}
else if( 2 == argc )
{
std::cout << NtpClient::GetTime( argv[1] ) << '\n';
}
else
{
std::cerr
<< "Usage: " << argv[0]
<< " NTP-server\n NTP-server is pool.ntp.org if not specified\n";
return 1;
}
return 0;
}
The NtpClient class is coded as follows:
// NTP client uaing Boost::Asio.
// 2010-05-11
// Jansson Consulting
// http://www.p-jansson.com
// Dedicated to the Public Domain.
#ifndef NTPCLIENT_HPP
#define NTPCLIENT_HPP
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
class NtpClient
{
public:
static boost::posix_time::ptime GetTime()
{
return GetTime("pool.ntp.org");
};
static boost::posix_time::ptime GetTime( const char* ntpServer )
{
using boost::asio::ip::udp;
boost::asio::io_service io_service;
udp::resolver resolver(io_service);
udp::resolver::query query(udp::v4(), ntpServer, "ntp");
udp::endpoint receiver_endpoint = *resolver.resolve(query);
udp::endpoint sender_endpoint;
boost::uint8_t data[48] = {
0x1B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
udp::socket socket(io_service);
socket.open(udp::v4());
socket.send_to(
boost::asio::buffer(data),
receiver_endpoint);
socket.receive_from(
boost::asio::buffer(data),
sender_endpoint);
typedef boost::uint32_t u32;
const u32 iPart(
static_cast<u32>(data[40]) << 24
| static_cast<u32>(data[41]) << 16
| static_cast<u32>(data[42]) << 8
| static_cast<u32>(data[43])
);
const u32 fPart(
static_cast<u32>(data[44]) << 24
| static_cast<u32>(data[45]) << 16
| static_cast<u32>(data[46]) << 8
| static_cast<u32>(data[47])
);
using namespace boost::posix_time;
const ptime pt(
boost::gregorian::date(1900,1,1),
milliseconds(
iPart * 1.0E3
+ fPart * 1.0E3 / 0x100000000ULL )
);
return pt;
};
};
#endif
When linking, you have to include the boost_date_time and boost_system libraries.
Update 2010-06-15: I have built this program for Microsoft Windows in another post.
0 kommentarer:
Post a Comment