Java實現客戶端與服務器端的時間同步


在客戶端獲取的當前時間和在服務端獲取的當前時間往往會存在差異。有時我們需要知道在客戶端創建數據時,相對於服務器的時間是多少。這是我們需要知道客戶端和服務端獲取當前時間的時間差,從而可以算出相對於服務器的時間。主要的過程分為:“在客戶端啟動時,請求服務器端,發送當前客戶端時間T1”、“服務器端收到請求,返回T2和T3,T2表示獲取到客戶端請求的時間,T3表示響應客戶端請求的時間”、“客戶端收到服務器的響應后,記錄當前時間T4”、“算出客戶端和服務端的時間差TimeDifference”。

1、在客戶端啟動時,請求服務器端,發送當前客戶端時間T1。

在客戶端定義個long類型的變量,存儲時間差,初始值為0:

/**
 * 同步Ntp時,服務器與POS之間的時差
 */
public static long TimeDifference;


/**
 * 同步APP的時間和服務器的時間
 */
private void syncTime() {
    long timeStamp = new Date(System.currentTimeMillis() + NtpHttpBO.TimeDifference).getTime();
    if (!ntpHttpBO.syncTime(timeStamp)) {
        log.error("POS機啟動時,同步服務器時間失敗!");
        Toast.makeText(this, "POS機啟動時,同步服務器時間失敗!", Toast.LENGTH_SHORT).show();
    }
}

請求服務器時,將初始客戶端的時間戳作為t1參數,傳給服務器端:HTTP_Ntp_SyncTime = "ntp/syncEx.bx?t1=":

public boolean syncTime(long timeStamp) {
    log.info("正在執行NtpHttpBO的syncTime,timeStamp=" + timeStamp);

    Request req = new Request.Builder()
            .url(Configuration.HTTP_IP + Ntp.HTTP_Ntp_SyncTime + timeStamp)
            .addHeader(BaseHttpBO.COOKIE, GlobalController.getInstance().getSessionID())
            .build();
    HttpRequestUnit hru = new NtpSync();
    hru.setRequest(req);
    hru.setTimeout(TIME_OUT);
    hru.setbPostEventToUI(true);
    httpEvent.setEventProcessed(false);
    httpEvent.setStatus(BaseEvent.EnumEventStatus.EES_Http_ToDo);
    hru.setEvent(httpEvent);
    NtpHttpBO.bForNtpOnly = true;
    HttpRequestManager.getCache(HttpRequestManager.EnumDomainType.EDT_Communication).pushHttpRequest(hru);

    log.info("正在請求服務器同步Ntp...");

    return true;
}

2、服務器端收到請求,返回T2和T3,T2表示獲取到客戶端請求的時間,T3表示響應客戶端請求的時間。

	@RequestMapping(value = "/syncEx", produces = "plain/text; charset=UTF-8", method = RequestMethod.GET)
	@ResponseBody
	public String syncEx(@ModelAttribute("SpringWeb") Ntp ntp, ModelMap model, HttpSession session) {
		if (!canCallCurrentAction(session, BaseAction.EnumUserScope.STAFF.getIndex())) {
			logger.debug("無權訪問本Action");
			return null;
		}

		ntp.setT2(new Date().getTime());

		Map<String, Object> params = new HashMap<String, Object>();

		ntp.setT3(new Date().getTime());

		params.put(BaseAction.KEY_Object, ntp);
		params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_NoError.toString());
		params.put(KEY_HTMLTable_Parameter_msg, "同步成功!");
		return JSONObject.fromObject(params, JsonUtil.jsonConfig).toString();
	}

3、客戶端收到服務器的響應后,記錄當前時間T4。

log.info(" Http onResponse,收到服務器的響應");
if (NtpHttpBO.bForNtpOnly) {// 在同步的時候設置POS接收到答復的時間,用於POS機與服務器同步時間
    event.setData(new Date(System.currentTimeMillis() + NtpHttpBO.TimeDifference).getTime());
    NtpHttpBO.bForNtpOnly = false;
}

存儲到NTP對象的t4屬性中:

long t4 = (long) getData(); // 在同步的時候設置POS接收到答復的時間,用於POS機與服務器時間同步,獲取的是時間戳
log.info("ERT_NtpSync得到的對象是:" + ntp.toString());
ntp.setT4(t4);
setBaseModel1(ntp);

4、算出客戶端和服務端的時間差TimeDifference。

Ntp ntp = (Ntp) event.getBaseModel1();
NtpHttpBO.TimeDifference = ((ntp.getT2() - ntp.getT1()) + (ntp.getT3() - ntp.getT4())) / 2;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM