网站实时读取服务器时间,网络通信:从NTP服务器获取网络时间

今天带来的是一个UDP网络通信的扩展应用:通过向NTP服务器发起一个请求,从服务器获得当前准确的网络时间,然后通过串口打印出来。这个应用不是我的原创,实际上仅仅是从Arduino示范程序中拷贝过来,对于这些代码,我几乎没有做什么调整,甚至连程序的注释都保留了原貌。通过这个程序,可以看出Rainbow的UDP网络通信API完全和Arduino保持兼容。Arduino原创地址:http://arduino.cc/en/Tutorial/UdpNtpClient

下图是程序运行后,通过串口调试工具看到的效果:

0b4c4089091ebbf16f19e5d9c739ee61.png

在软件包的“Projects\UDP-NtpClient”文件夹包含了本文的完整工程,可以直接编译、烧写和调试。程序代码如下,程序逻辑比较简单,请自行分析:

#include "WProgram.h"

#include "Ethernet.h"

#include "EthernetUDP.h"

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

unsigned int localPort = 8888;      // local port to listen for UDP packets

IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server

// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov NTP server

// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov NTP server

const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

// A UDP instance to let us send and receive packets over UDP

EthernetUDP Udp;

// send an NTP request to the time server at the given address

void sendNTPpacket(IPAddress& address)

{

// set all bytes in the buffer to 0

memset(packetBuffer, 0, NTP_PACKET_SIZE);

// Initialize values needed to form NTP request

// (see URL above for details on the packets)

packetBuffer[0] = 0xe3;  // LI, Version, Mode

packetBuffer[1] = 0;     // Stratum, or type of clock

packetBuffer[2] = 6;     // Polling Interval

packetBuffer[3] = 0xEC;  // Peer Clock Precision

// 8 bytes of zero for Root Delay & Root Dispersion

packetBuffer[12]  = 49;

packetBuffer[13]  = 0x4E;

packetBuffer[14]  = 49;

packetBuffer[15]  = 52;

// all NTP fields have been given values, now

// you can send a packet requesting a timestamp:

Udp.beginPacket(address, 123); //NTP requests are to port 123

Udp.write(packetBuffer,NTP_PACKET_SIZE);

Udp.endPacket();

}

void setup()

{

// Open serial communications and wait for port to open:

Serial.begin(9600);

while (!Serial)

{

; // wait for serial port to connect. Needed for Leonardo only

}

// start Ethernet and UDP

if (Ethernet.begin(mac) == 0)

{

Serial.println("Failed to configure Ethernet using DHCP");

// no point in carrying on, so do nothing forevermore:

for(;;)

;

}

Udp.begin(localPort);

}

void loop()

{

sendNTPpacket(timeServer); // send an NTP packet to a time server

// wait to see if a reply is available

delay(1000);

if ( Udp.parsePacket() )

{

// We've received a packet, read the data from it

Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

//the timestamp starts at byte 40 of the received packet and is four bytes,

// or two words, long. First, esxtract the two words:

unsigned long highWord = (packetBuffer[40] << 8) | packetBuffer[41];

unsigned long lowWord = (packetBuffer[42] << 8) | packetBuffer[43];

// combine the four bytes (two words) into a long integer

// this is NTP time (seconds since Jan 1 1900):

unsigned long secsSince1900 = highWord << 16 | lowWord;

Serial.print("Seconds since Jan 1 1900 = " );

Serial.println(secsSince1900);

// now convert NTP time into everyday time:

Serial.print("Unix time = ");

// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:

const unsigned long seventyYears = 2208988800UL;

// subtract seventy years:

unsigned long epoch = secsSince1900 - seventyYears;

// print Unix time:

Serial.println(epoch);

// print the hour, minute and second:

Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)

Serial.print((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)

Serial.print(':');

if ( ((epoch % 3600) / 60) < 10 )

{

// In the first 10 minutes of each hour, we'll want a leading '0'

Serial.print('0');

}

Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)

Serial.print(':');

if ( (epoch % 60) < 10 )

{

// In the first 10 seconds of each minute, we'll want a leading '0'

Serial.print('0');

}

Serial.println(epoch `); // print the second

}

// wait ten seconds before asking for the time again

delay(10000);

}

int main()

{

//初始化Rainbow

boardInit();

setup();

while(1) loop();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值