SNTP客户端版本4

时间:2015-12-23 16:22:21

标签: c sockets network-programming ntp

我无法理解代码的问题。

//SNTP Client  

#include <inttypes.h>   //(since C99)   Format conversion of integer types
#include <stdio.h>      //Input/output example printf
#include <stdlib.h>     //General utilities: memory management, program utilities, string conversions, random numbers
#include <unistd.h>     //standard symbolic constants and types
#include <string.h>     //string operations
#include <sys/types.h>  //data types
#include <sys/socket.h> //Internet Protocol family
#include <netinet/in.h> //Internet address family
#include <netdb.h>      //definitions for network database operations
#include <time.h>       //time types
#include <sys/time.h>   //time types
#include <arpa/inet.h>  //definitions for internet operations
//#include<linux/time.h>//time types in linux



//struct for gettimeofday
typedef struct {
    long tv_sec;
    long tv_usec;
} timeval;


struct packets
{
    uint8_t LIVNMODE; 
    uint8_t startum; 
    uint8_t poll; 
    uint8_t precision; 
    uint32_t Root_Delay; 
    uint32_t Root_Dispersion; 
    uint32_t Ref_Identifier; 
    uint32_t Ref_T; 
    uint32_t Ref_Tp2; 
    uint32_t Origin_T;  
    uint32_t Origin_Tp2; 
    uint32_t Receive_T; 
    uint32_t Receive_Tp2; 
    uint32_t T_T; 
    uint32_t T_Tp2; 
};


int main(int argc, char *argv[])
{
int sock_desc;
socklen_t len; 
int today_time;

struct sockaddr_in Cli_addr,Serv_addr; 
struct packets message_send;
struct packets message_receive; 

//add all packets in initialization 
//LI, VN and MODE in a one bytes as a 00 100 011 eg VN=4
message_send.LIVNMODE=0b00100011; 
message_send.startum=0;
message_send.poll=0;
message_send.precision=0;
message_send.Root_Delay=0;
message_send.Root_Dispersion=0;
message_send.Ref_Identifier=0;
message_send.Ref_T=0;
message_send.Ref_Tp2=0;
message_send.Origin_T=0;
message_send.Origin_Tp2=0;
message_send.Receive_T=0;
message_send.Receive_Tp2=0;
message_send.T_T=0;
message_send.T_Tp2=0;


message_receive.Ref_T=0;
message_receive.Ref_Tp2=0;
message_receive.Origin_T=0;
message_receive.Origin_Tp2=0;
message_receive.Receive_T=0;
message_receive.Receive_Tp2=0;
message_receive.T_T=0;
message_receive.T_Tp2=0;
char * HOSTADDRESS;
int PORT;

if (argc>=2){
      HOSTADDRESS=(char *)argv[1]; 
      PORT = atoi(argv[2]);
}
else{
    printf("--------------------------------------------\n");
    printf("usage: ./file.out HOST_ADDRESS PORT \n");
    printf("--------------------------------------------\n");
    return -1;
}


if ((sock_desc = socket(AF_INET,SOCK_DGRAM,0)) < 0){
    printf("Error: can't create the socket ");
    return -1; 
}


len=sizeof(struct sockaddr_in);   
bzero((char *) &Serv_addr,sizeof(Serv_addr));    
Serv_addr.sin_family = AF_INET; 
Serv_addr.sin_addr.s_addr=inet_addr(HOSTADDRESS); 
Serv_addr.sin_port=ntohs(PORT);    


if(sendto(sock_desc,&message_send,sizeof(message_send),0,(struct sockaddr *)&Serv_addr,len) < 0){
     printf("Error: can not send a message on a socket");
     return -1;
}

if(recvfrom(sock_desc,&message_receive,sizeof(message_receive),0,(struct sockaddr *)&Cli_addr,&len) < 0){
     printf("Error: can not receive a message on a socket");
     return -1;
}
printf("message_receive.Ref_T: %" PRIu32 "\n",message_receive.Ref_T);
printf("message_receive.Ref_Tp2: %" PRIu32 "\n",message_receive.Ref_Tp2);
printf("message_receive.Origin_T: %" PRIu32 "\n",message_receive.Origin_T);
printf("message_receive.Origin_Tp2: %" PRIu32 "\n",message_receive.Origin_Tp2);
printf("message_receive.Receive_T: %" PRIu32 "\n",message_receive.Receive_T);
printf("message_receive.Receive_Tp2: %" PRIu32 "\n",message_receive.Receive_Tp2);
printf("message_receive.T_T: %" PRIu32 "\n",message_receive.T_T);
printf("message_receive.T_Tp2: %" PRIu32 "\n",message_receive.T_Tp2);
int receive_T=ntohl(message_receive.Receive_T);
today_time = receive_T-2208988800; 
printf("Today time is: %s",ctime((const long *)&today_time));
}

此代码是我的perl代码的翻译版本。我知道收到的消息值与服务器发送的不一样。因为我正在查看wireshark,它正在发送正确的数据包,但无法理解如何解决它。

编辑:所以我必须是直接的。这是输出!日期总是不同的。

输出1:

message_receive.Ref_T: 4232652250
message_receive.Ref_Tp2: 684824910
message_receive.Origin_T: 0
message_receive.Origin_Tp2: 0
message_receive.Receive_T: 1112352218
message_receive.Receive_Tp2: 1556395294
message_receive.T_T: 1112352218
message_receive.T_Tp2: 2125642782
Today time is: Tue Dec 26 01:44:10 4248

1分钟后另一个输出2:

message_receive.Ref_T: 4232652250
message_receive.Ref_Tp2: 684824910
message_receive.Origin_T: 0
message_receive.Origin_Tp2: 0
message_receive.Receive_T: 3796706778
message_receive.Receive_Tp2: 260377675
message_receive.T_T: 3796706778
message_receive.T_Tp2: 3180073547
Today time is: Mon Dec 11 17:18:34 4197

请帮助!!!

2 个答案:

答案 0 :(得分:1)

服务器以网络字节序发送数据,您需要将它们转换为主机字节序。请参阅ntohs(), ntohl()

答案 1 :(得分:1)

结果证明转换是个问题。

time_t total_secs;
int Receive_T=ntohl(message_receive.T_T);
Receive_T = Receive_T - 2208988800L;
total_secs = Receive_T;
printf("Today time is: %s",ctime((const long *)&total_secs));

我必须将时间转换为time_t或转换,如果使用localtimectime则无关紧要。