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

📄 main.c

📁 linux下的获取Internet time的程式
💻 C
📖 第 1 页 / 共 5 页
字号:
            weeble *= WEEBLE_FACTOR;            x -= 3600.0*(i = (int)(x/3600.0));            x -= 60.0*(j = (int)(x/60.0));            if (i > 0)                fprintf(stderr,"%s: after %d hours %d mins ",argv0,i,j);            else if (j > 0)                fprintf(stderr,"%s: after %d mins %.0f secs ",argv0,j,x);            else                fprintf(stderr,"%s: after %.1f secs ",argv0,x);            fprintf(stderr,"%.0f acc. %.0f rej. %.0f b'cast\n",                            successes,failures,broadcasts);        }/* Respond to incoming requests or plaster broadcasts over the net.  Note thatwe could skip almost all of the decoding, but it provides a healthy amount oferror detection.  We could print some information on incoming packets, but thecode is not structured to do this very helpfully. */        i = read_packet(0,&data,&x,&y);        if (i == 2) {            ++broadcasts;            return 0;        } else if (i != 0) {            ++failures;            return i;        } else {            ++successes;            make_packet(&data,NTP_SERVER);        }    } else {        do_nothing(period);        make_packet(&data,NTP_BROADCAST);    }    if (verbose > 2) {        fprintf(stderr,"Outgoing packet:\n");        display_data(&data);    }    pack_ntp(transmit,NTP_PACKET_MIN,&data);    if (verbose > 2) display_packet(transmit,NTP_PACKET_MIN);    return write_socket(0,transmit,NTP_PACKET_MIN);}double estimate_stats (int *a_total, int *a_index, data_record *record,    double correction, double *a_disp, double *a_when, double *a_offset,    double *a_error, double *a_drift, double *a_drifterr, int *a_wait,    int update) {/* This updates the running statistics and returns the best estimate of what todo now.  It returns the timestamp relevant to the correction.  If broadcastsare rare and the drift is large, it will fail - you should then use a bettersynchronisation method.  It will also fail if something goes severely wrong(e.g. if the local clock is reset by another process or the transmission errorsare beyond reason).There is a kludge for synchronisation loss during down time.  If it detectsthis, it will update only the history data and return zero; this is thenhandled specially in run_daemon().  While it could correct the offset, thismight not always be the right thing to do. */    double weight, disp, when, offset, error, drift, drifterr,        now, e, w, x, y, z;    int total = *a_total, index = *a_index, wait = *a_wait, i;    char text[50]; /* Correct the previous data and store a new entry in the circular buffer. */    for (i = 0; i < total; ++i) {        record[i].when += correction;        record[i].offset -= correction;    }    if (update) {        record[index].dispersion = *a_disp;        record[index].when = *a_when;        record[index].offset = *a_offset;        if (verbose > 1)            fprintf(stderr,"%s: corr=%.3f when=%.3f disp=%.3f off=%.3f",                argv0,correction,*a_when,*a_disp,*a_offset); /* See below */        if (operation == op_listen) {            if (verbose > 1) fprintf(stderr,"\n");            record[index].error = minerr;            record[index].weight = 1.0;        } else {            if (verbose > 1) fprintf(stderr," err=%.3f\n",*a_error);            record[index].error = x = *a_error;            record[index].weight = 1.0/(x > minerr ? x*x : minerr*minerr);        }        if (++index >= count) index = 0;        *a_index = index;        if (++total > count) total = count;        *a_total = total;        if (verbose > 2)            fprintf(stderr,"corr=%.6f tot=%d ind=%d\n",correction,total,index);    }/* If there is insufficient data yet, use the latest estimates and returnforthwith.  Note that this will not work for broadcasts, but they will bedisabled in run_daemon(). */    if ((operation == op_listen && total < count && update) || total < 3) {        *a_drift = 0.0;        *a_drifterr = -1.0;        *a_wait = delay;        return *a_when;    }/* Work out the average time, offset, error etc.  Note that the dispersion isnot subject to the central limit theorem.  Unfortunately, the variation in thesource's dispersion is our only indication of how consistent its clock is. */    disp = weight = when = offset = y = 0.0;    for (i = 0; i < total; ++i) {        weight += w = record[i].weight;        when += w*record[i].when;        offset += w*record[i].offset;        y += w*record[i].dispersion;        if (disp < record[i].dispersion)            disp = record[i].dispersion;    }    when /= weight;    offset /= weight;    y /= weight;    if (verbose > 2)        fprintf(stderr,"disp=%.6f wgt=%.3f when=%.6f off=%.6f\n",            disp,weight,when,offset);/* If there is enough data, estimate the drift and errors by regression.  Notethat it is essential to calculate the mean square error, not the mean error. */    error = drift = x = z = 0.0;    for (i = 0; i < total; ++i) {        w = record[i].weight/weight;        x += w*(record[i].when-when)*(record[i].when-when);        drift += w*(record[i].when-when)*(record[i].offset-offset);        z += w*(record[i].offset-offset)*(record[i].offset-offset);        error += w*record[i].error*record[i].error+            2.0*w*(record[i].dispersion-y)*(record[i].dispersion-y);    }    if (verbose > 2)        fprintf(stderr,"X2=%.3f XY=%.6f Y2=%.9f E2=%.9f ",x,drift,z,error);/* When calculating the errors, add some paranoia mainly to check for codingerrors and complete lunacy, attempting to retry if at all possible.  Becauseglitches at this point are so common, log a reset even in non-verbose mode.There will be more thorough checks later.  Note that we cannot usefully checkthe error for broadcasts. */    z -= drift*drift/x;    if (verbose > 2) fprintf(stderr,"S2=%.9f\n",z);    if (! update) {        if (z > 1.0e6)            fatal(0,"stored data too unreliable for time estimation",NULL);    } else if (operation == op_client) {        e = error+disp*disp+minerr*minerr;        if (z > e) {            if (verbose || z >= maxerr*maxerr)                fprintf(stderr,                    "%s: excessively high error %.3f > %.3f > %.3f\n",                    argv0,sqrt(z),sqrt(e),sqrt(error));            if (total <= 1)                return 0.0;            else if (z < maxerr*maxerr) {                sprintf(text,"resetting on error %.3g > %.3g",                    sqrt(z),sqrt(e));                log_message(text);                return 0.0;            } else                fatal(0,"incompatible (i.e. erroneous) timestamps",NULL);        } else if (z > error && verbose)            fprintf(stderr,                "%s: anomalously high error %.3f > %.3f, but < %.3f\n",                argv0,sqrt(z),sqrt(error),sqrt(e));    } else {        if (z > maxerr*maxerr)            fatal(0,"broadcasts too unreliable for time estimation",NULL);    }    drift /= x;    drifterr = ABSCISSA*sqrt(z/(x*total));    error = (operation == op_listen ? minerr : 0.0)+ABSCISSA*sqrt(z/total);    if (verbose > 2)        fprintf(stderr,"err=%.6f drift=%.6f+/-%.6f\n",error,drift,drifterr);    if (error+drifterr*delay > NTP_INSANITY)        fatal(0,"unable to get a reasonable drift estimate",NULL);/* Estimate the optimal short-loop period, checking it carefully.  Remember tocheck that this whole process is likely to be accurate enough and that thedelay function may be inaccurate. */    wait = delay;    x = (drift < 0.0 ? -drift : drift);    if (! update)        ;    else if (x*delay < 0.5*minerr) {        if (verbose > 2) fprintf(stderr,"Drift too small to correct\n");    } else if (x < 2.0*drifterr) {        if (verbose > 2)            fprintf(stderr,"Drift correction suppressed\n");    } else {        if ((z = drifterr*delay) < 0.5*minerr) z = 0.5*minerr;        wait = (x < z/delay ? delay : (int)(z/x+0.5));        wait = (int)(delay/(int)(delay/(double)wait+0.999)+0.999);        if (wait > delay)            fatal(0,"internal error in drift calculation",NULL);        if (drift*wait > maxerr || wait < RESET_MIN) {            sprintf(text,"%.6f+/-%.6f",drift,drifterr);            fatal(0,"drift correction too large: %s",text);        }    }    if (wait < *a_wait/2) wait = *a_wait/2;    if (wait > *a_wait*2) wait = *a_wait*2;/* Now work out what the correction should be, as distinct from what it shouldhave been, remembering that older times are less certain. */    now = current_time(JAN_1970);    x = now-when;    offset += x*drift;    error += x*drifterr;    for (i = 0; i < total; ++i) {        x = now-record[i].when;        z = record[i].error+x*drifterr;        if (z < error) {            when = record[i].when;            offset = record[i].offset+x*drift;            error = z;        }    }    if (verbose > 2)        fprintf(stderr,"now=%.6f when=%.6f off=%.6f err=%.6f wait=%d\n",            now,when,offset,error,wait);/* Finally, return the result. */    *a_disp = disp;    *a_when = when;    *a_offset = offset;    *a_error = error;    *a_drift = drift;    *a_drifterr = drifterr;    *a_wait = wait;    return now;}double correct_drift (double *a_when, double *a_offset, double drift) {/* Correct for the drift since the last time it was done, provided that a longenough time has elapsed.  And do remember to kludge up the time anddiscrepancy, when appropriate. */    double d, x;    d = current_time(JAN_1970)-*a_when;    *a_when += d;    x = *a_offset+d*drift;    if (verbose > 2)        fprintf(stderr,"Correction %.6f @ %.6f off=%.6f ",x,*a_when,*a_offset);    if (d >= waiting && (x < 0.0 ? -x : x) >= 0.5*minerr) {        if (verbose > 2) fprintf(stderr,"performed\n");        adjust_time(x,(action == action_reset ? 1 : 0),0.5*minerr);        *a_offset = 0.0;        return x;    } else {        if (verbose > 2) fprintf(stderr,"ignored\n");        *a_offset = x;        return 0.0;    }}void handle_saving (int operation, int *total, int *index, int *cycle,    data_record *record, double *previous, double *when, double *correction) {/* This handles the saving and restoring of the state to a file.  While it issubject to spoofing, this is not a major security problem.  But, out of generalparanoia, check everything in sight when restoring.  Note that this functionhas no external effect if something goes wrong. */    struct {        data_record record[COUNT_MAX];        double previous, when, correction;        int operation, delay, count, total, index, cycle, waiting;    } buffer;    double x, y;    int i, j;    if (savefile == NULL) return;/* Read the restart file and print its data in diagnostic mode.  Note that somecare is necessary to avoid introducing a security exposure - but we trust theC library not to trash the stack on bad numbers! */    if (operation == save_read_only || operation == save_read_check) {        if (fread(&buffer,sizeof(buffer),1,savefile) != 1 || ferror(savefile)) {            if (ferror(savefile))                fatal(1,"unable to read record from daemon save file",NULL);            else if (verbose)                fprintf(stderr,"%s: bad daemon restart information\n",argv0);            return;        }        if (verbose > 2) {            fprintf(stderr,"Reading prev=%.6f when=%.6f corr=%.6f\n",                buffer.previous,buffer.when,buffer.correction);            fprintf(stderr,"op=%d dly=%d cnt=%d tot=%d ind=%d cyc=%d wait=%d\n",                buffer.operation,buffer.delay,buffer.count,buffer.total,                buffer.index,buffer.cycle,buffer.waiting);            if (buffer.total < COUNT_MAX)                for (i = 0; i < buffer.total; ++i)                    fprintf(stderr,                        "disp=%.6f wgt=%.3f when=%.6f off=%.6f err=%.6f\n",                        buffer.record[i].dispersion,buffer.record[i].weight,                        buffer.record[i].when,buffer.record[i].offset,                        buffer.record[i].error);        }/* Start checking the data for sanity. */        if (buffer.operation == 0 && buffer.delay == 0 && buffer.count == 0) {            if (operation < 0)                fatal(0,"the daemon save file has been cleared",NULL);            if (verbose)                fprintf(stderr,"%s: restarting from a cleared file\n",argv0);            return;        }        if (operation == save_read_check) {            if (buffer.operation != operation || buffer.delay != delay ||                    buffer.count != count) {                if (verbose)                    fprintf(stderr,"%s: different parameters for restart\n",

⌨️ 快捷键说明

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