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

📄 sntp.cpp

📁 简单网络时间协议实现的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
{
  m_Time = time.m_Time;
  return *this;
}

double CNtpTime::operator-(const CNtpTime& time) const
{
  if (m_Time >= time.m_Time)
	{
    CNtpTime diff;
		diff.m_Time = m_Time - time.m_Time;
		return diff.Seconds() + NtpFractionToSecond(diff.Fraction());
	}
	else
	{
	  CNtpTime diff;
		diff.m_Time = time.m_Time - m_Time;
		return -(diff.Seconds() + NtpFractionToSecond(diff.Fraction()));
	}
}

CNtpTime CNtpTime::operator+(const double& timespan) const
{
  CNtpTime rVal;
	rVal.m_Time = m_Time;

  if (timespan >= 0)
	{
	  unsigned __int64 diff = ((unsigned __int64) timespan) << 32;
    double intpart;
	  double frac = modf(timespan, &intpart);
	  diff += (unsigned __int64) (frac * 0xFFFFFFFF);

		rVal.m_Time += diff;
	}
	else
	{
    double d = -timespan;
	  unsigned __int64 diff = ((unsigned __int64) d) << 32;
    double intpart;
	  double frac = modf(d, &intpart);
		diff += (unsigned __int64) (frac * 0xFFFFFFFF);

		rVal.m_Time -= diff;
	}

	return rVal;
}

CNtpTime::operator SYSTEMTIME() const
{
  //Currently this function only operates correctly in 
  //the 1900 - 2036 primary epoch defined by NTP

  SYSTEMTIME st;
  DWORD s = Seconds();
  st.wSecond = (WORD)(s % 60);
  s /= 60;
  st.wMinute = (WORD)(s % 60);
  s /= 60;
  st.wHour = (WORD)(s % 24);
  s /= 24;
  long JD = s + JAN_1ST_1900;
  st.wDayOfWeek = (WORD)((JD + 1) % 7);
  GetGregorianDate(JD, st.wYear, st.wMonth, st.wDay);
  st.wMilliseconds = NtpFractionToMs(Fraction());

  return st;
}

DWORD CNtpTime::Seconds() const
{
  return (DWORD) ((m_Time & 0xFFFFFFFF00000000) >> 32);
}

DWORD CNtpTime::Fraction() const
{
  return (DWORD) (m_Time & 0xFFFFFFFF);
}

CNtpTime::operator CNtpTimePacket() const
{
  CNtpTimePacket ntp;
  ntp.m_dwInteger = htonl(Seconds());
  ntp.m_dwFractional = htonl(Fraction());
	return ntp;
}

CNtpTime CNtpTime::GetCurrentTime()
{
  SYSTEMTIME st;
  GetSystemTime(&st);
	CNtpTime t(st);
  return t;
}

DWORD CNtpTime::MsToNtpFraction(WORD wMilliSeconds)
{
  ASSERT(wMilliSeconds < 1000);
	return m_MsToNTP[wMilliSeconds];
}

WORD CNtpTime::NtpFractionToMs(DWORD dwFraction)
{
	return (WORD)((((double)dwFraction) * NTP_FRACTIONAL_TO_MS) + 0.5);
}

double CNtpTime::NtpFractionToSecond(DWORD dwFraction)
{
  double d = (double)dwFraction;
	d *= NTP_TO_SECOND;
	return ((double)dwFraction) * NTP_TO_SECOND;
}



CSNTPClient::CSNTPClient()
{
  m_dwTimeout = 5000; //Default timeout of 5 seconds
  m_nProxyPort = 1080;
  m_bProxy = FALSE;
}

BOOL CSNTPClient::GetServerTime(LPCTSTR pszHostName, NtpServerResponse& response, int nPort)
{
	//For correct operation of the T2A macro, see MFC Tech Note 59
	USES_CONVERSION;

	//paramater validity checking
  ASSERT(pszHostName);

  //Create the socket, Allocated of the heap so we can control
  //the time when it's destructor is called. This means that
  //we can call SetLastError after its destructor
  CWSocket* pSocket = new CWSocket();
  try
  {
    if (m_bProxy)
      pSocket->Create(FALSE); //TCP if going thro a proxy
    else
      pSocket->Create(TRUE); //UDP otherwise
  }
  catch(CWSocketException* pEx)
  {
    pEx->Delete();
    TRACE(_T("Failed to create client socket, GetLastError returns: %d\n"), GetLastError());
    return FALSE;
  }

  //Connect to the SNTP server (or Socks Proxy)
  try
  {
    if (m_bProxy)
    {
      if (m_sLocalBoundAddress.GetLength())
      {
        if (m_sProxyUserName.GetLength())
          pSocket->ConnectViaSocks5(pszHostName, nPort, m_sProxyServer, m_nProxyPort, m_sProxyUserName, m_sProxyPassword, m_sLocalBoundAddress, m_dwTimeout, TRUE);
        else
          pSocket->ConnectViaSocks5(pszHostName, nPort, m_sProxyServer, m_nProxyPort, NULL, NULL, m_sLocalBoundAddress, m_dwTimeout, TRUE);
      }
      else
      {
        if (m_sProxyUserName.GetLength())
          pSocket->ConnectViaSocks5(pszHostName, nPort, m_sProxyServer, m_nProxyPort, m_sProxyUserName, m_sProxyPassword, NULL, m_dwTimeout, TRUE);
        else
          pSocket->ConnectViaSocks5(pszHostName, nPort, m_sProxyServer, m_nProxyPort, NULL, NULL, NULL, m_dwTimeout, TRUE);
      }
    }
    else    
    {
      if (m_sLocalBoundAddress.GetLength())
        pSocket->Connect(pszHostName, nPort, m_sLocalBoundAddress);
      else
        pSocket->Connect(pszHostName, nPort);
    }
  }
  catch(CWSocketException* pEx)
  {
    TRACE(_T("Could not connect to the SNTP server %s on port %d, GetLastError returns: %d\n"), pszHostName, nPort, pEx->m_nError);

    //Tidy up prior to returning
    delete pSocket;
    SetLastError(pEx->m_nError);

    pEx->Delete();

    return FALSE;
  }

  //Initialise the NtpBasicInfo packet
  NtpBasicInfo nbi;
  int nSendSize = sizeof(NtpBasicInfo);
  memset(&nbi, 0, nSendSize);
  nbi.m_LiVnMode = 27; //Encoded representation which represents NTP Client Request & NTP version 3.0 (i.e. LI=0, VN=3, Mode=3)
  nbi.m_TransmitTimestamp = CNtpTime::GetCurrentTime();

  //Send off the NtpBasicInfo packet
  try
  {
    pSocket->Send(&nbi, nSendSize);
  }
  catch(CWSocketException* pEx)
  {
    TRACE(_T("Failed in call to send NTP request to the SNTP server, GetLastError returns %d\n"), pEx->m_nError);

    //Tidy up prior to returning
    delete pSocket;
    SetLastError(pEx->m_nError);

    pEx->Delete();

    return FALSE;
  }

  //Need to use select to determine readibilty of socket
  BOOL bReadable = FALSE;
  try
  {
    bReadable = pSocket->IsReadible(m_dwTimeout);
  }
  catch(CWSocketException* pEx)
  {
    pEx->Delete();
    bReadable = FALSE;
  }

  if (!bReadable)
  {
    TRACE(_T("Unable to wait for NTP reply from the SNTP server, GetLastError returns %d\n"), WSAETIMEDOUT);

    //Tidy up prior to returning
    delete pSocket;
    SetLastError(WSAETIMEDOUT);

    return FALSE;
  }
  response.m_DestinationTime = CNtpTime::GetCurrentTime();

  //read back the response into the NtpFullPacket struct
  NtpFullPacket nfp;
  int nReceiveSize = sizeof(NtpFullPacket);
  memset(&nfp, 0, nReceiveSize);
  try
  {
    pSocket->Receive(&nfp, nReceiveSize);
  }
  catch(CWSocketException* pEx)
  {
    TRACE(_T("Unable to read reply from the SNTP server, Error returns %d\n"), pEx->m_nError);

    //Tidy up prior to returning
    DWORD dwError = GetLastError();
    delete pSocket;
    SetLastError(pEx->m_nError);

    pEx->Delete();

    return FALSE;
  }

  //Transfer all the useful info into the response structure
  response.m_nStratum = nfp.m_Basic.m_Stratum;
  response.m_nLeapIndicator = (nfp.m_Basic.m_LiVnMode & 0xC0) >> 6;
	response.m_OriginateTime = nfp.m_Basic.m_OriginateTimestamp;
  response.m_ReceiveTime = nfp.m_Basic.m_ReceiveTimestamp;
  response.m_TransmitTime = nfp.m_Basic.m_TransmitTimestamp;
  response.m_RoundTripDelay = (response.m_DestinationTime - response.m_OriginateTime) - (response.m_ReceiveTime - response.m_TransmitTime);
  response.m_LocalClockOffset = ((response.m_ReceiveTime - response.m_OriginateTime) + (response.m_TransmitTime - response.m_DestinationTime)) / 2;

  //Tidy up prior to returning
  delete pSocket;

  return TRUE;
}

//AR 22-07-2000
#ifndef _WIN32_WCE
BOOL CSNTPClient::EnableSetTimePriviledge()
{
  BOOL bOpenToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | 
                                     TOKEN_QUERY, &m_hToken);

  m_bTakenPriviledge = FALSE;
  if (!bOpenToken) 
  {
    if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 
    {
      //Must be running on 95 or 98 not NT. In that case just ignore the error
      SetLastError(ERROR_SUCCESS);
      return TRUE;
    }
    TRACE(_T("Failed to get Adjust priviledge token\n"));
    return FALSE;
  }
  ZeroMemory(&m_TokenPriv, sizeof(TOKEN_PRIVILEGES));
  if (!LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &m_TokenPriv.Privileges[0].Luid))
  {
    TRACE(_T("Failed in callup to lookup priviledge\n"));
    return FALSE;
  }
  m_TokenPriv.PrivilegeCount = 1;
  m_TokenPriv.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;
  m_bTakenPriviledge = TRUE;

  BOOL bSuccess = AdjustTokenPrivileges(m_hToken, FALSE, &m_TokenPriv, 0, NULL, 0);
	if (!bSuccess)
	  TRACE(_T("Failed to adjust SetTime priviledge\n"));

	return bSuccess;
}
#endif

//AR 22-07-2000
#ifndef _WIN32_WCE
void CSNTPClient::RevertSetTimePriviledge()
{
  if (m_bTakenPriviledge) 
  {
    m_TokenPriv.Privileges[0].Attributes &= (~SE_PRIVILEGE_ENABLED);
    if (!AdjustTokenPrivileges(m_hToken, FALSE, &m_TokenPriv, 0, NULL, 0))
		  TRACE(_T("Failed to reset SetTime priviledge\n"));
    CloseHandle(m_hToken);
  }
}
#endif

BOOL CSNTPClient::SetClientTime(const CNtpTime& NewTime)
{
  BOOL bSuccess = FALSE;
//AR 22-07-2000
#ifndef _WIN32_WCE
  if (EnableSetTimePriviledge())
  {
#endif
	  SYSTEMTIME st = NewTime;
    bSuccess = SetSystemTime(&st);
    if (!bSuccess)
      TRACE(_T("Failed in call to set the system time\n"));
//AR 22-07-2000
#ifndef _WIN32_WCE
  }
  RevertSetTimePriviledge();
#endif
  return bSuccess;
}

⌨️ 快捷键说明

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