⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 linux下的获取Internet time的程式
💻 C
📖 第 1 页 / 共 5 页
字号:
    for (i = 0; i < 8; ++i) {        if ((k = (int)(d *= 256.0)) >= 256) k = 255;        packet[NTP_TRANSMIT+i] = k;        d -= k;    }}void unpack_ntp (ntp_data *data, unsigned char *packet, int length) {/* Unpack the essential data from an NTP packet, bypassing struct layout andendian problems.  Note that it ignores fields irrelevant to SNTP. */    int i;    double d;    data->current = current_time(JAN_1970);    /* Best to come first */    data->status = (packet[0] >> 6);    data->version = (packet[0] >> 3)&0x07;    data->mode = packet[0]&0x07;    data->stratum = packet[1];    data->polling = packet[2];    data->precision = packet[3];    d = 0.0;    for (i = 0; i < 4; ++i) d = 256.0*d+packet[NTP_DISP_FIELD+i];    data->dispersion = d/65536.0;    d = 0.0;    for (i = 0; i < 8; ++i) d = 256.0*d+packet[NTP_REFERENCE+i];    data->reference = d/NTP_SCALE;    d = 0.0;    for (i = 0; i < 8; ++i) d = 256.0*d+packet[NTP_ORIGINATE+i];    data->originate = d/NTP_SCALE;    d = 0.0;    for (i = 0; i < 8; ++i) d = 256.0*d+packet[NTP_RECEIVE+i];    data->receive = d/NTP_SCALE;    d = 0.0;    for (i = 0; i < 8; ++i) d = 256.0*d+packet[NTP_TRANSMIT+i];    data->transmit = d/NTP_SCALE;}void make_packet (ntp_data *data, int mode) {/* Create an outgoing NTP packet, either from scratch or starting from arequest from a client.  Note that it implements the NTP specification, evenwhen this is clearly misguided, except possibly for the setting of LI.  Itwould be easy enough to add a sanity flag, but I am not in the business ofdesigning an alternative protocol (however much better it might be). */    data->status = NTP_LI_FUDGE<<6;    data->stratum = NTP_STRATUM;    data->reference = data->dispersion = 0.0;    if (mode == NTP_SERVER) {        data->mode = (data->mode == NTP_CLIENT ? NTP_SERVER : NTP_PASSIVE);        data->originate = data->transmit;        data->receive = data->current;    } else {        data->version = NTP_VERSION;        data->mode = mode;        data->polling = NTP_POLLING;        data->precision = NTP_PRECISION;        data->receive = data->originate = 0.0;    }    data->current = data->transmit = current_time(JAN_1970);}int read_packet (int which, ntp_data *data, double *off, double *err) {/* Check the packet and work out the offset and optionally the error.  Notethat this contains more checking than xntp does.  This returns 0 for success, 1for failure and 2 for an ignored broadcast packet (a kludge for servers).  Note that it must not change its arguments if it fails. */    unsigned char receive[NTP_PACKET_MAX+1];    double delay1, delay2, x, y;    int ret, response = 0, failed, length, i, k;/* Read the packet and deal with diagnostics. */    if (ret = read_socket(which,receive,NTP_PACKET_MAX+1,waiting,&length))        return ret;    if (length < NTP_PACKET_MIN || length > NTP_PACKET_MAX) {        if (verbose)            fprintf(stderr,"%s: bad length %d for NTP packet on socket %d\n",                argv0,length,which);        return 1;    }    if (verbose > 2) {        fprintf(stderr,"Incoming packet on socket %d:\n",which);        display_packet(receive,length);    }    unpack_ntp(data,receive,length);    if (verbose > 2) display_data(data);/* Start by checking that the packet looks reasonable.  Be a little paranoid,but allow for version 1 semantics and sick clients. */    if (operation == op_server) {        if (data->mode == NTP_BROADCAST) return 2;        failed = (data->mode != NTP_CLIENT && data->mode != NTP_ACTIVE);    } else if (operation == op_listen)        failed = (data->mode != NTP_BROADCAST);    else {        failed = (data->mode != NTP_SERVER && data->mode != NTP_PASSIVE);        response = 1;    }    if (failed || data->status != 0 || data->version < 1 ||            data->version > NTP_VERSION_MAX ||            data->stratum > NTP_STRATUM_MAX) {        if (verbose)            fprintf(stderr,                "%s: totally spurious NTP packet rejected on socket %d\n",                argv0,which);        return 1;    }/* Note that the conventions are very poorly defined in the NTP protocol, so wehave to guess.  Any full NTP server perpetrating completely unsynchronisedpackets is an abomination, anyway, so reject it. */    delay1 = data->transmit-data->receive;    delay2 = data->current-data->originate;    failed = ((data->stratum != 0 && data->stratum != NTP_STRATUM_MAX &&                data->reference == 0.0) ||            (operation != op_server && data->transmit == 0.0));    if (response &&            (data->originate == 0.0 || data->receive == 0.0 ||                (data->reference != 0.0 && data->receive < data->reference) ||                delay1 < 0.0 || delay1 > NTP_INSANITY || delay2 < 0.0 ||                data->dispersion > NTP_INSANITY))        failed = 1;    if (failed) {        if (verbose)            fprintf(stderr,                "%s: incomprehensible NTP packet rejected on socket %d\n",                argv0,which);        return 1;    }/* If it is a response, check that it corresponds to one of our requests andhas got here in a reasonable length of time. */    if (response) {        k = 0;        for (i = 0; i < attempts; ++i)            if (data->originate == outgoing[i]) {                outgoing[i] = 0.0;                ++k;            }        if (k != 1 || delay2 > NTP_INSANITY) {            if (verbose)                fprintf(stderr,                    "%s: bad response from NTP server rejected on socket %d\n",                    argv0,which);            return 1;        }    }/* Now return the time information.  If it is a server response, it containsenough information that we can be almost certain that we have not been fooledtoo badly.  Heaven help us with broadcasts - make a wild kludge here, and seeelsewhere for other kludges. */    if (dispersion < data->dispersion) dispersion = data->dispersion;    if (operation == op_listen || operation == op_server) {        *off = data->transmit-data->current;        *err = NTP_INSANITY;    } else {        x = data->receive-data->originate;        y = (data->transmit == 0.0 ? 0.0 : data->transmit-data->current);        *off = 0.5*(x+y);        *err = x-y;        x = data->current-data->originate;        if (0.5*x > *err) *err = 0.5*x;    }    return 0;}void format_time (char *text, int length, double offset, double error,    double drift, double drifterr) {/* Format the current time into a string, with the extra information asrequested.  Note that the rest of the program uses the correction needed, whichis what is printed for diagnostics, but this formats the error in the localsystem for display to users.  So the results from this are the negation ofthose printed by the verbose options. */    int milli, len;    time_t now;    struct tm *gmt;    static const char *months[] = {        "Jan", "Feb", "Mar", "Apr", "May", "Jun",        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"    };/* Work out and format the current local time.  Note that some semi-ANSIsystems do not set the return value from (s)printf. */    now = convert_time(current_time(offset),&milli);    errno = 0;    if ((gmt = localtime(&now)) == NULL)        fatal(1,"unable to work out local time",NULL);    len = 24;    if (length <= len) fatal(0,"internal error calling format_time",NULL);    errno = 0;    sprintf(text,"%.4d %s %.2d %.2d:%.2d:%.2d.%.3d",            gmt->tm_year+1900,months[gmt->tm_mon],gmt->tm_mday,            gmt->tm_hour,gmt->tm_min,gmt->tm_sec,milli);    if (strlen(text) != len)        fatal(1,"unable to format current local time",NULL);/* Append the information about the offset, if requested. */    if (error >= 0.0) {        if (length < len+30)            fatal(0,"internal error calling format_time",NULL);        errno = 0;        sprintf(&text[len]," %c %.3f +/- %.3f secs",(offset > 0.0 ? '-' : '+'),                (offset > 0.0 ? offset : -offset),dispersion+error);        if (strlen(&text[len]) < 22)            fatal(1,"unable to format clock correction",NULL);    }/* Append the information about the drift, if requested. */    if (drifterr >= 0.0) {        len = strlen(text);        if (length < len+25)            fatal(0,"internal error calling format_time",NULL);        errno = 0;        sprintf(&text[len]," %c %.1f +/- %.1f ppm",                (drift > 0.0 ? '-' : '+'),1.0e6*fabs(drift),                1.0e6*drifterr);        if (strlen(&text[len]) < 17)            fatal(1,"unable to format clock correction",NULL);    }/* It would be better to check for field overflow, but it is a lot of code totrap extremely implausible scenarios.  This will usually stop chaos fromspreading. */    if (strlen(text) >= length)        fatal(0,"internal error calling format_time",NULL);}double reset_clock (double offset, double error, int daemon) {/* Reset the clock, if appropriate, and return the correction actually used.This contains most of the checking for whether changes are worthwhile, exceptin daemon mode. */    double absoff = (offset < 0 ? -offset : offset);    char text[50];/* If the correction is large, ask for confirmation before proceeding. */    if (absoff > prompt) {        if (! daemon && ftty(stdin) && ftty(stdout)) {            printf("The time correction is %.3f +/- %.3f+%.3f seconds\n",                offset,dispersion,error);            printf("Do you want to correct the time anyway? ");            fflush(stdout);            if (toupper(getchar()) != 'Y') {                printf("OK - quitting\n");                fatal(0,NULL,NULL);            }        } else {            sprintf(text,"%.3f +/- %.3f+%.3f",offset,dispersion,error);            fatal(0,"time correction too large: %s seconds",text);        }    }/* See if the correction is reasonably reliable and worth making. */    if (absoff < (daemon ? 0.5 : 1.0)*minerr) {        if (daemon ? verbose > 1 : verbose)            fprintf(stderr,"%s: correction %.3f +/- %.3f+%.3f secs - ignored\n",                argv0,offset,dispersion,error);        return 0.0;    } else if (absoff < 2.0*error) {        if (daemon ? verbose > 1 : verbose)            fprintf(stderr,                "%s: correction %.3f +/- %.3f+%.3f secs - suppressed\n",                argv0,offset,dispersion,error);        return 0.0;    }/* Make the correction.  Provide some protection against the previouscorrection not having completed, but it will rarely help much. */    adjust_time(offset,(action == action_reset ? 1 : 0),        (daemon ? 2.0*minerr : 0.0));    if (daemon ? verbose > 1 : verbose) {        format_time(text,50,0.0,-1.0,0.0,-1.0);        fprintf(stderr,            "%s: time changed by %.3f secs to %s +/- %.3f+%.3f\n",            argv0,offset,text,dispersion,error);    }    return offset;}int run_server (void) {/* In op_server mode, serves SNTP client requests; in op_broadcast mode,broadcasts SNTP packets. It is quite tricky to get this to fail, and it willusually indicate that the local system is sick.Note that in libmsntp, this call does not loop. In server mode, it listens forconnections until it receives one and replies, or it times out. In broadcastmode, it sends a broadcast packet and returns immediately. *//* In server mode, provide some tracing of normal running (but not too much,except when debugging!) */    unsigned char transmit[NTP_PACKET_MIN];    ntp_data data;    double started = current_time(JAN_1970), successes = 0.0, failures = 0.0,        broadcasts = 0.0, weeble = 1.0, x, y;    int i, j;    if (operation == op_server) {        x = current_time(JAN_1970)-started;        if (verbose && x/3600.0+successes+failures >= weeble) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -