www.pudn.com > Demo C.rar > ntp.c



struct {
    unsigned char livnmode, stratum, poll, prec;
    unsigned long delay, disp, refid;
    unsigned long reftime[2], origtime[2], rcvtime[2], txtime[2];
} pkt;

#define PORT 123
#define MY_OFFSET 2208988800L


/* Sync the time */
int 
Sync(char *hostname)
{
    int i, fd = -1, len, n, zonemin;
    struct sockaddr_in saddr, myaddr;
    struct hostent *hp;
    char answer[2000];
    unsigned long myt;
    long offset;
    fd_set readfds;
    struct timeval tv;

    /* Get server name */

    n = strlen(hostname);
    if (n <= 0) {
        perror("hostname");
        return 0;
    }
    sprintf(answer, "Connecting to %s\n", hostname);
    printf(answer);

    /* Resolve server name */

    bzero((char *)&saddr, sizeof saddr);
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(PORT);
    if ((saddr.sin_addr.s_addr = inet_addr(hostname)) == ERROR) {
        perror("unknown server");
        return 0;
    }
    sprintf(answer, "Hostname resolved, getting the socket\n");
    printf(answer);

    /* Get a socket */
        
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket");
        return 0;
    }
        
    sprintf(answer, "Got socket, bind to port\n");
    printf(answer);
    /* Bind it to some port */

    bzero((char *)&myaddr, sizeof myaddr);
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(3030);
    myaddr.sin_addr.s_addr = INADDR_ANY;

    if (bind(fd, (struct sockaddr *) &myaddr, sizeof myaddr) < 0) {
        perror("bind error");
        close(fd);
        return 0;
    }

    /* Fill in the request packet */

    bzero((char *)&pkt, sizeof pkt);
    pkt.livnmode = 0x0b;        /* version 1, mode 3 (client) */

    sprintf(answer, "Send packet\n");
    printf(answer);
    /* Send packet to server */
        
    if ((n = sendto(fd, (char *)&pkt, sizeof pkt, 0, 
                        (struct sockaddr *) &saddr, 
                        sizeof saddr)) != sizeof pkt) {
        sprintf(answer, "sendto %d err %d", n, errno);
        perror(answer);
        close(fd);
        return 0;
    }

    sprintf(answer, "Wait for reply\n");
    printf(answer);
    /* Read reply packet from server */
    len = sizeof pkt;
    FD_SET(fd, &readfds);
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    if(select(fd+1, &readfds, NULL, NULL, &tv)){
        if ((n = recvfrom(fd, (char *)&pkt, sizeof pkt, 0, 
                              (struct sockaddr *) &saddr, 
                              &len)) != sizeof pkt) {
            sprintf(answer, "recvfrom %d err %d", n, errno);
            perror(answer);
            close(fd);
            return 0;
        }
    }
    else {
        perror("Timeout");
        close(fd);
        return 0;
    }
    sprintf(answer, "Sanitu check\n");
    printf(answer);
    /* Sanity checks */

    if ((pkt.livnmode & 0xc0) == 0xc0 || !pkt.stratum || !pkt.txtime[0]) {
        perror("server not synchronized");
        close(fd);
        return 0;
    }

    /*
     * NTP timestamps are represented as a 64-bit unsigned fixed-
     * point number, in seconds relative to 0h on 1 January 1900. The integer
     * part is in the first 32 bits and the fraction part in the last 32 bits.
     */

    myt = ntohl(pkt.txtime[0]) - MY_OFFSET;
    offset = myt - time(NULL);
        
    sprintf(answer, "Time: %s\nstratum %d offset %ld\n", 
                        ctime(&myt), (int) pkt.stratum, offset);
        
    if (fd >= 0) {
        close(fd);
    }
    printf(answer);
    return 1;
}