一个简单的NTP客户端demo
2012-10-10 19:24
357 查看
// 一个简单的NTP客户端demo // NTP协议参考:http://www.enhan.com.cn/blog/index.php/tech/520 // 代码参考:http://blog.csdn.net/kviling/article/details/7088943 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <time.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define SECONDS_1900_1970 0x83AA7E80 // 1900/1/1 至 1970/1/1 的秒数 #define NTP_SRV_PORT 123 #define NTP_PACKET_LEN 48 #define TIMEOUT 1 // 一些可用的NTP服务器 #define NTP_SERVER_0 "218.75.4.130" #define NTP_SERVER_1 "114.80.81.1" #define NTP_SERVER_2 "202.120.2.101" #define NTP_SERVER_3 "210.72.145.44" static void construct_ntp_packet(char content[]) { memset(content, 0, NTP_PACKET_LEN); content[0] = 0x1b; // LI(2bit) = 0; VN(3bit) = 3; Mode(3bit) = 3 (client); 00 011 011 -> 00011011 -> 0x1b } int get_ntp_time(int sockfd, struct sockaddr_in *server_addr, struct tm *net_tm) { char content[256]; time_t timet; long temp; int addr_len = 16; struct timeval block_time; fd_set sockfd_set; FD_ZERO(&sockfd_set); FD_SET(sockfd, &sockfd_set); block_time.tv_sec = TIMEOUT; //recv timeout block_time.tv_usec = 0; construct_ntp_packet(content); if (sendto(sockfd, content, NTP_PACKET_LEN, 0, (struct sockaddr *)server_addr, addr_len) < 0) { perror("sendto error"); return (-1); } if (select(sockfd + 1, &sockfd_set, NULL, NULL, &block_time ) > 0) { memset(content, 0, sizeof(content)); if (recvfrom(sockfd, content, sizeof(content), 0, (struct sockaddr *)server_addr, (socklen_t *)&addr_len) < 0) { perror("recvfrom error"); return (-1); } else { memcpy(&temp, content + 40, 4); //提取服务器端设置的transmit_timastamp temp = (time_t)(ntohl(temp) - SECONDS_1900_1970); timet = (time_t)temp; memcpy(net_tm, gmtime(&timet), sizeof(struct tm)); net_tm->tm_hour = net_tm->tm_hour + 8; //北京时间,东八区 } } else { return (-1); } return (0); } int main(void) { int sockfd, i; struct tm *net_tm; struct sockaddr_in addr; char ip[4][16]= {{NTP_SERVER_0}, {NTP_SERVER_1}, {NTP_SERVER_2}, {NTP_SERVER_3}}; net_tm = (struct tm *)malloc(sizeof(struct tm)); for (i = 0; i < 4; i++) { memset(&addr, 0, sizeof(addr)); addr.sin_addr.s_addr = inet_addr(ip[i]); addr.sin_port = htons(NTP_SRV_PORT); if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { perror("socket error"); return (-1); } printf("IP:[%s]\n", ip[i]); memset(net_tm, 0, sizeof(struct tm)); if (get_ntp_time(sockfd, &addr, net_tm) == 0) { printf("NTP:[%d/%d/%d %d:%d:%d]\n\n", net_tm->tm_year+1900, net_tm->tm_mon+1, net_tm->tm_mday, net_tm->tm_hour, net_tm->tm_min, net_tm->tm_sec); } else { printf("failed!!!\n\n"); } close(sockfd); } return (0); }
相关文章推荐
- 一个简单的Http客户端Demo
- 一个简单的DNS客户端demo
- 一个利用WinInet通信的简单客户端Demo
- 无废话WCF入门教程六[一个简单的Demo]
- 一个简单的c语言版的DNS解析客户端,能提供解析耗时
- 基于socket的客户端和服务端聊天简单使用 附Demo
- Nodejs实现的一个简单udp广播服务器、客户端
- 一个简单的缓存Demo
- 关于ListView控件使用的个人总结--以一个简单的新闻客户端开发为例
- 一个简单的直播 IOS客户端 + 服务端
- 自己写一个简单的Web服务器(附Demo)
- 关于EF的一个简单Demo
- libevent实现的一个简单的服务器和客户端程序
- Golang的一个简单实用的http客户端库httpc
- Demo2 模拟简单登陆 客户端代码
- Java Socket编程服务器端和客户端的一个简单实例
- 一个简单的TCP 客户端时间获取程序 ipv4/ipv6
- 一个简单的UDP程序—C++服务器和C# .NET客户端
- mapreduce里程计算的一个简单的reduce计算demo
- 一台电脑只能启动一个客户端。——Mutex 类的简单运用