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

📄 ntpsock.cpp

📁 linux程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// NtpSock.cpp: implementation of the CNtpSock class.
//
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>

#include "NtpSock.h"
#ifdef __Win32__
    #include <Ws2tcpip.h>
    
#endif

#ifdef __REDHATLINUX__
    #include <sys/types.h>
    //#include <cygwin/in.h>
    #include <netinet/in.h>
#endif

static unsigned int mInitCount = 0;
static bool InitWS2_32()
{
	bool success = true;
 	#ifdef __Win32__
        if(!mInitCount)
        {
            WSADATA stWSAData;
            success = !WSAStartup(0x0101, &stWSAData);
        }
        mInitCount ++;
    #endif
        
    return success;
}
    
static void ShutdownWS2_32()
{
	bool success = true;
    #ifdef __Win32__
  	    mInitCount--;
        if(!mInitCount)
        {
            WSACleanup();
        }
    #endif
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CNtpSocket::CNtpSocket()
{
	#ifdef __Win32__
	InitWS2_32();
    m_hSocket = INVALID_SOCKET; //default to an invalid scoket descriptor
    #endif
}

CNtpSocket::~CNtpSocket()
{
	#ifdef __Win32__
	    ShutdownWS2_32();
        Close();
    #endif    
    
}

Bool8 CNtpSocket::Create(int type)
{
    //NTP Uses UDP instead of the usual TCP
    m_hSocket = socket(AF_INET,type, 0);
	if(m_hSocket == INVALID_SOCKET)
		return false;
	if(SetSockBlock(0))
		return false;
	if(ReuseAddr())
		return false;

    return true;
}

Bool8 CNtpSocket::Connect(char *pszHostAddress, int nPort)
{
    //must have been created first
    //ASSERT(m_hSocket != INVALID_SOCKET);
	//Determine if the address is in dotted notation
	struct sockaddr_in sockAddr;
	// ZeroMemory(&sockAddr, sizeof(sockAddr));
	memset(&sockAddr,0,sizeof(sockAddr));
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_port = htons((u_short)nPort);
	sockAddr.sin_addr.s_addr = inet_addr(pszHostAddress);
	//If the address is not dotted notation, then do a DNS 
	//lookup of it.
	if (sockAddr.sin_addr.s_addr == INADDR_NONE)
	{
		/*
		LPHOSTENT lphost;
		lphost = gethostbyname(pszHostAddress);
		if (lphost != NULL)
			sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
		else
		*/
		return false;
	}

	//Call the protected version which takes an address 
	//in the form of a standard C style struct.
	return Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));
}

Bool8 CNtpSocket::Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen)
{
	int nConnect = connect(m_hSocket, lpSockAddr, nSockAddrLen);
    return (nConnect == 0);
}

int CNtpSocket::Send(char *pszBuf, int nBuf,struct sockaddr_in *toAddr)
{
    //must have been created first
    //ASSERT(m_hSocket != INVALID_SOCKET);

    int len = sizeof(struct sockaddr);
    len = sendto(m_hSocket, pszBuf, nBuf, 0,(struct sockaddr *)toAddr,len);
    return len;
}

int CNtpSocket::Receive(LPSTR pszBuf, int nBuf, struct sockaddr_in *fromAddr)
{
    //must have been created first
    //ASSERT(m_hSocket != INVALID_SOCKET);

    // struct sockaddr FAR* from,  
    // int FAR* fromlen  
    //socklen_t len = sizeof(sockaddr);
    //return recvfrom(m_hSocket, pszBuf, nBuf, 0, (struct sockaddr *)fromAddr, &len); 
   	char rcvBuf[200];
	int rcvBufLen = 200;
	memset(rcvBuf,0,sizeof(rcvBuf));

	int minLen = sizeof(NtpBasicInfo);
	
	#ifdef __Win32__
	int len = sizeof(sockaddr);
	#endif
	
	#ifdef __REDHATLINUX__
	socklen_t len = sizeof(sockaddr);
	#endif
	
    int retLen = recvfrom(m_hSocket, rcvBuf, rcvBufLen, 0, (struct sockaddr *)fromAddr, &len); 
    
	if(retLen >= minLen)
	{
		memcpy(pszBuf,rcvBuf,nBuf);
		return retLen;
	}
	else
		return -1;

}

void CNtpSocket::Close()
{
	if (m_hSocket != INVALID_SOCKET)
	{
		shutdown(m_hSocket,2);
		#ifdef __Win32__
		    closesocket(m_hSocket);
		#else
		    close(m_hSocket);
		#endif    
	}
}

int CNtpSocket::IsReadible(unsigned long dwTimeout)
{
    timeval timeout;
    timeout.tv_sec = dwTimeout / 1000;
    timeout.tv_usec = dwTimeout % 1000;
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(m_hSocket, &fds);
    int nStatus;
    #ifdef __Win32__
    nStatus = select(0, &fds, NULL, NULL,NULL); // &timeout);
    #else
    //nStatus = select(1, &fds, NULL, NULL,NULL);
    nStatus = select(FD_SETSIZE + 1, &fds, NULL, NULL,NULL);
    #endif
	return nStatus;
}

int CNtpSocket::Bind(unsigned short port)
{
	struct sockaddr_in addr1;
	int len = sizeof(addr1);
    addr1.sin_family = AF_INET;
    addr1.sin_port = htons(port);
    addr1.sin_addr.s_addr = INADDR_ANY;
    
    int err = ::bind(m_hSocket, (sockaddr *)&addr1,len);
    if (err == INVALID_SOCKET)
    {
        return err;
    }
        
    return err;
}

int CNtpSocket::ReuseAddr()
{ 
	int one = 1;
    int err = ::setsockopt(m_hSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(int));
    
	return err;

}

int CNtpSocket::NoDelay()
{
	int one = 1;
    int err = ::setsockopt(m_hSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(int));
        
	return err;
 
}

int CNtpSocket::KeepAlive()
{
	int one = 1;
    int err = ::setsockopt(m_hSocket, SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(int));
 
	return err;
 
}

int CNtpSocket::SetLoopBack(int lb)
{
	const int loopback = lb; //0; //禁止回馈
    int ret = setsockopt(m_hSocket,IPPROTO_IP,IP_MULTICAST_LOOP,(char*)&loopback,sizeof(loopback));
	return ret;
}
 
int CNtpSocket::SetSocketSndBufSize(unsigned int inNewSize)
{
	int bufSize = inNewSize;
    int err = ::setsockopt(m_hSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bufSize, sizeof(int));
    
	return err;

}

int CNtpSocket::SetSocketRcvBufSize(unsigned int inNewSize)
{
	int bufSize = inNewSize;
    int err = ::setsockopt(m_hSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bufSize, sizeof(int));
    return err;

}

int CNtpSocket::SetSockBlock(unsigned long blockingIO)
{
	int err;
	#ifdef __Win32__
        err = ioctlsocket(m_hSocket, FIONBIO, &blockingIO);
    #else
        err = ioctl(m_hSocket, FIONBIO, &blockingIO);
    #endif
    return err;
}

int CNtpSocket::SetSockBroadcast(unsigned long broadcast)       
{
	int err;
	#ifdef __Win32__
   	    err = setsockopt(m_hSocket, SOL_SOCKET, SO_BROADCAST, (char*)&broadcast,sizeof(broadcast));
   	#else
  	     //U32 notblock = broadcast; //nonblockingIO;
         err = ioctl(m_hSocket, FIONBIO, &broadcast);

   	#endif
    return err;

}

int CNtpSocket::SetIPLoop()
{
	int loop = 1; 
    int err = setsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
    return err;
}

int CNtpSocket::SetSockMulticast(char *multicastAddr, bool isTrue)
{
	int err = 0;
	// #ifdef __Win32__
	struct ip_mreq mreq;
    memset(&mreq, 0, sizeof(mreq));
    mreq.imr_interface.s_addr = INADDR_ANY;
    mreq.imr_multiaddr.s_addr = inet_addr(multicastAddr); //MULTICAST_IP);
 
	if(isTrue)
        //加入一个多播组
        err = setsockopt(m_hSocket,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mreq,sizeof(mreq));
	else
        //加入一个多播组
        err = setsockopt(m_hSocket,IPPROTO_IP,IP_DROP_MEMBERSHIP,(char*)&mreq,sizeof(mreq));
 	// #endif
 	
	return err;
}       

#ifdef __Win32__
DWORD WINAPI _StartDataRecvThread( LPVOID param )
#else
void* _StartDataRecvThread( void * param )
#endif
{
	CConnectionPeer *pConn = (CConnectionPeer *) param;
	pConn->DataRecvThread();
	#ifdef __Win32__
	    return 0;
	#endif
	
}

#ifdef __Win32__
DWORD WINAPI _StartDataSendThread( LPVOID param )
#else
void* _StartDataSendThread( void * param )
#endif
{
	CConnectionPeer *pConn = (CConnectionPeer *) param;
	pConn->DataSendThread();
	#ifdef __Win32__
	    return 0;
	#endif
	
}

#ifdef __Win32__
DWORD WINAPI _StartMultiCastSendThread( LPVOID param )
#else
void* _StartMultiCastSendThread( void * param )
#endif
{
	CConnectionPeer *pConn = (CConnectionPeer *) param;
	pConn->MultiCastSendThread();
	#ifdef __Win32__
	    return 0;
	#endif
}

CConnectionPeer::CConnectionPeer(unsigned int castType,Bool8 isServer,char *serverAddr,unsigned short port)
{
	mIsServer = isServer;
	mCastType = castType;
	mUniCastPeriod = 5000;
	memset(mServerAddr,0,sizeof(mServerAddr));
	if(mIsServer)
	{
		if(serverAddr != NULL)
			strcpy(mServerAddr,serverAddr);
	}
	mLocalPort = port;
	#ifdef __Win32__
	mRecvThreadHandle = NULL;
	mMultiCastThreadHandle = NULL;
	m_hToken = NULL;
	#else
	mRecvThreadHandle = 0;
	mMultiCastThreadHandle = 0;
	
	#endif
	mServerPort  = port;
	pLog = NULL;
	mMultiCastPeriod = 1000;
	memset(mMultiCastAddr,0,sizeof(mMultiCastAddr));
	mIsGetNetDelay   = false;
	mIsGetServerAddr = false;
	mNetDelay        = 0;

}

CConnectionPeer::~CConnectionPeer()
{

}

int CConnectionPeer::DealRecvData()
{
	return OS_NoError;
}

int CConnectionPeer::SendTimeSynData()
{
	if( mServerAddr == NULL)
		return OS_HasError;
    
	struct sockaddr_in toAddr;
	memset(&toAddr,0,sizeof(toAddr));

	if( mIsServer )
		toAddr.sin_port = htons(mServerPort);
	else
		toAddr.sin_port = htons(mLocalPort);

	toAddr.sin_family    = AF_INET;
	toAddr.sin_addr.s_addr = inet_addr(mServerAddr);
	NtpBasicInfo nbi;
	memset(&nbi,0,sizeof(nbi));
    int nSendSize = sizeof(NtpBasicInfo);
    // ZeroMemory(&nbi, nSendSize);
    memset(&nbi,0,nSendSize);
	nbi.m_LiVnMode = 35; //Encoded representation which represents NTP Client Request & NTP version 3.0
	
    // only test
/*  CNtpTime testTm1 = CNtpTime::GetCurrentTime();
    SYSTEMTIME st = SYSTEMTIME(testTm1);
    printf("st 请求消息发送以前时间,%04d-%02d-%02d %02d:%02d:%02d:%03d \n",
	st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
 */   // test end

    nbi.m_TransmitTimestamp = CNtpTime::GetCurrentTime();

    //Send off the NtpBasicInfo packet
    if (!mPeerSocket.Send((char *)&nbi, nSendSize, &toAddr))
        return OS_HasError;
    if(pLog)
	{
		if(mIsServer)
			pLog->AddMsgIntoTail("服务器成功发送时间同步请求");
		else
			pLog->AddMsgIntoTail("客户机成功发送时间同步请求");

	}

	return OS_NoError;
}

void CConnectionPeer::DataRecvThread()
{
	char logBuffer[500];
	//char timeBuffer[500];
    NtpFullPacket nfp;
	NtpServerResponse response;
	struct sockaddr_in fromAddr;

	while(1)
	{
		int lRet = mPeerSocket.IsReadible(0);
		if( lRet < 0 ) 
           return;
		else if( lRet == 0 )
		{
			#ifdef __Win32__
			    Sleep(1000);
			#endif
			#ifdef __REDHATLINUX__
			    usleep(1000*1000);
			#endif
            continue;
		}
        response.m_DestinationTime = CNtpTime::GetCurrentTime();
        //read back the response into the NtpFullPacket struct
        int nReceiveSize = sizeof(NtpFullPacket);
        //ZeroMemory(&nfp, nReceiveSize);
        memset(&nfp,0,sizeof(nfp));
		memset(&fromAddr,0,sizeof(fromAddr));
        lRet = mPeerSocket.Receive((char *) &nfp, nReceiveSize, &fromAddr);
		if( lRet < 0)
            continue;
	
		response.m_DestinationTime = CNtpTime::GetCurrentTime();
        char mode;
		mode = nfp.m_Basic.m_LiVnMode & 0x07;
		
		
		//if( pLog )
		//{
			memset(logBuffer, 0, sizeof(logBuffer));
			if( mode == 4 )     /// 服务器发来的响应消息
			    sprintf(logBuffer, "收到服务器的响应消息,地址%s 端口 %d", 
				inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port));
            else if( mode == 3) /// 客户端发来的请求消息
			    sprintf(logBuffer, "收到客户端发来的请求消息,地址%s 端口 %d", 
				inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port));
			else if( mode == 5) /// 服务器多播消息
			    sprintf(logBuffer, "收到服务器多播消息,地址%s 端口 %d", 
				inet_ntoa(fromAddr.sin_addr),ntohs(fromAddr.sin_port));
			if(pLog)
			    pLog->AddMsgIntoTail(logBuffer);
		//}
		

		/// 服务器处理响应客户端单播请求
		if( mIsServer )
		{
			//if( (mode == 3) || ( (mode == 5) && GetIsUniCast() ))
			if( mode == 3 )
			{
			    /// 回复客户端
			    ///Li = 0   Vn保存  Mode=4 Stratum=1
			    nfp.m_Basic.m_LiVnMode = ( nfp.m_Basic.m_LiVnMode & 0xF8) + 4;
			    nfp.m_Basic.m_Stratum  = 1;
			    /// 保留Poll
			    /// 
			    nfp.m_Basic.m_RootDelay = 0;
			    nfp.m_Basic.m_RootDispersion = 0;
			    nfp.m_Basic.m_ReferenceID[0] = 0; //NULL;
			    nfp.m_Basic.m_ReferenceTimestamp.m_dwFractional = 0;
                nfp.m_Basic.m_ReferenceTimestamp.m_dwInteger    = 0;
			
			    nfp.m_Basic.m_OriginateTimestamp = nfp.m_Basic.m_TransmitTimestamp;
			    nfp.m_Basic.m_ReceiveTimestamp   = response.m_DestinationTime;
			    nfp.m_Basic.m_TransmitTimestamp  = CNtpTime::GetCurrentTime();
		        //int nSendSize = sizeof(NtpBasicInfo);
			    int nSendSize = sizeof(NtpFullPacket);
			    lRet = mPeerSocket.Send((char *) &nfp, nSendSize, &fromAddr);
			    if( lRet == nSendSize )
				{
				    strcpy(logBuffer,"服务器成功发送响应");
				    pLog->AddMsgIntoTail(logBuffer);
				}
			    else
				{
				    strcpy(logBuffer,"服务器发送响应消息失败");
				    pLog->AddMsgIntoTail(logBuffer);
				}
			}
			/// 服务器和外部时钟服务器进行时间同步
		    else if( mode == 4 )
			{
	            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;
                
			    RepairSystemTime(&response);
			}

		}
		/// 客户机处理服务器响应 
		if(!mIsServer)  
		{
			if( mode == 4 )
			{
				/// 处理通常单播
				if( !(mIsAnyCast || mIsMultiCast) )
				{
					SYSTEMTIME st;

⌨️ 快捷键说明

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