c - ntp 服务器丢包。怎么解决?选择不工作
问题描述
出于某种原因,我不知道有时我的设备没有收到来自 ntp 服务器的答复,而是卡在了读取套接字中。我尝试使用选择来解决这个问题。但我总是超时。使用 select 有什么问题?它总是返回 0 而不是字节数
int ntp_get_time(char *host_name) {
int sockfd, n; // Socket file descriptor and the n return result from writing/reading from the socket.
int portno = 123; // NTP UDP port number.
// Structure that defines the 48 byte NTP packet protocol.
// Create and zero out the packet. All 48 bytes worth.
ntp_packet packet = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
memset(&packet, 0, sizeof(ntp_packet));
// Set the first byte's bits to 00,011,011 for li = 0, vn = 3, and mode = 3. The rest will be left set to zero.
*((char *) &packet + 0) = 0x1b; // Represents 27 in base 10 or 00011011 in base 2.
// Create a UDP socket, convert the host-name to an IP address, set the port number,
// connect to the server, send the packet, and then read in the return packet.
struct sockaddr_in serv_addr; // Server address data structure.
struct hostent *server; // Server data structure.
sockfd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Create a UDP socket.
if (sockfd < 0) {
dlog_print(DLOG_ERROR, LOG_TAG, "ERROR opening socket");
if (sockfd)
close(sockfd); // [joao]
return -1;
}
dlog_print(DLOG_INFO, LOG_TAG, "host_name: %s", host_name);
server = gethostbyname(host_name); // Convert URL to IP.
if (server == NULL) {
dlog_print(DLOG_ERROR, LOG_TAG, "ERROR, no such host");
if (sockfd)
close(sockfd); // [joao]
return -1;
}
// Zero out the server address structure.
bzero((char*) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
// Copy the server's IP address to the server address structure.
bcopy((char*) server->h_addr, ( char* ) &serv_addr.sin_addr.s_addr, server->h_length );
// Convert the port number integer to network big-endian style and save it to the server address structure.
serv_addr.sin_port = htons(portno);
// Call up the server using its IP address and port number.
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))
< 0) {
dlog_print(DLOG_ERROR, LOG_TAG, "ERROR connecting");
if (sockfd)
close(sockfd); // [joao]
return -1;
}
else {
dlog_print(DLOG_INFO, LOG_TAG, "conect sockect success");
}
struct timeval t0;
int res = 0;
res = gettimeofday(&t0, NULL);
dlog_print(DLOG_INFO, LOG_TAG, "gettimeofday res = %d", res);
// Send it the NTP packet it wants. If n == -1, it failed.
n = write(sockfd, (char*) &packet, sizeof(ntp_packet));
if (n < 0) {
dlog_print(DLOG_ERROR, LOG_TAG, "ERROR writing to socket");
if (sockfd)
close(sockfd); // [joao]
return -1;
}
else {
dlog_print(DLOG_INFO, LOG_TAG, "write sockect success");
}
// Wait and receive the packet back from the server. If n == -1, it failed.
fd_set rfds;
struct timeval timeout;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(sockfd, &rfds);
/* Wait up to five seconds. */
timeout.tv_sec = 2;
timeout.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &timeout);
/* Don't rely on the value of tv now! */
if (retval == -1) {
dlog_print(DLOG_INFO, LOG_TAG, "error in select =%d", retval);
return retval;
}
else if (retval) {
n = read(sockfd, (char*) &packet, sizeof(ntp_packet));
dlog_print(DLOG_INFO, LOG_TAG, "read sockfd n =%d", n);
}
else {
dlog_print(DLOG_INFO, LOG_TAG, "No data within 2 seconds retval =%d", retval);
return retval;
}
解决方案
推荐阅读
- javascript - 为什么我的 viewModel 在 HTML 中更新,而不是在我的 javascript 中?
- angular - Angular 创建一个 SELECT 分组选项
- amazon-web-services - AWS AppSync 中的 N+1 个查询
- css - SVG 进度条在圆圈的 75 比例上虚线
- android - 单元测试视图模型
- c# - 将数据绑定到数据上下文之外的类的实例
- php - 如何插入来自我网站的页面和发布者的 ID?
- gradle - Gradle - 配置配置文件报告的输出文件名
- java - 使线程从主线程等待
- android - Android Parcelable - 如何在另一个自定义对象数组中传递自定义对象数组