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

📄 server.c

📁 由于linux作服务器运行时,时常会出现系统时间不正确现象,现提供完整的时间服务器和客户端程序,由window提供时间服务器端供多台Linux服务器获取window上时间并做出时间调整.
💻 C
字号:
#include "Server.h"


BOOL		 g_isMainThreadContinue = FALSE ;	
BOOL		 g_isWorkThreadContinue = FALSE ;
HANDLE		 g_hMainThreadEndEvent = NULL;
char		 g_strIpAddr[32];
ULONG		 g_LastError = 0;

THREADCONTEXT	g_ThreadContextList[MAX_THREAD];



static SOCKET     g_hSocketTimeServer;
/****************************************************************************************/
static SOCKET CreateServiceSocket(unsigned long dwIPAddr, unsigned short wPort)
{
	SOCKET          hSocket;
	SOCKADDR_IN     SocketIn;

	hSocket = socket( PF_INET , SOCK_STREAM , IPPROTO_TCP );
	if( hSocket == INVALID_SOCKET ) 
	{
		UpdateLogFile( "创建锁(CreateServiceSocket)失败!" );
		return INVALID_SOCKET;
	}

	SocketIn.sin_family      = AF_INET;
	SocketIn.sin_addr.s_addr = dwIPAddr ;//htonl (dwIPAddr);
	SocketIn.sin_port        = htons (wPort);
	if( bind( hSocket , (struct sockaddr*)&SocketIn , sizeof( SocketIn ) ) < 0 )
	{
		closesocket (hSocket);
		UpdateLogFile( "bind失败!" );
		return INVALID_SOCKET;
	}
	if( listen( hSocket , 30 ) < 0 )
	{
		closesocket( hSocket );
		UpdateLogFile( "listen失败!" );
		return INVALID_SOCKET;
	}

	return hSocket;
}


DWORD WINAPI WorkThread( LPVOID lpParameter )
{
	ULONG			ID = (ULONG) lpParameter ;
	PTHREADCONTEXT	pThreadContext = NULL;
	fd_set			fdRead;
	struct timeval			TimeVal;
	int				nRet;
	char*			Buffer = NULL;
	SYSTEMTIME		SystemTime;
	ULONG			lOffset = 0;
	ULONG			lFrameLen = 0;
	LONGLONG		T2 = 0 , T3 = 0;

	Buffer = (char*)malloc( MAX_BUFFER );

	if( ID >= MAX_THREAD )
	{
		pThreadContext = (PTHREADCONTEXT)lpParameter ; 
	}
	else
	{
		pThreadContext = &g_ThreadContextList[ID];
	}

	while( pThreadContext->isContinue )
	{
		//看看是否有任务
		if( ID < MAX_THREAD )
		{
			if( WAIT_OBJECT_0 != WaitForSingleObject( pThreadContext->hJobEvent , 0 ) )
			{
				pThreadContext->isBusy = FALSE;
				Sleep( 500 );
				continue;
			}
			ResetEvent( pThreadContext->hJobEvent );
		}
		
		memset( Buffer , 0 , MAX_BUFFER );
		//有新任务
		while( TRUE )
		{
			FD_ZERO( &fdRead );
			FD_SET( pThreadContext->ConnSocket , &fdRead );
			TimeVal.tv_sec = 0;
			TimeVal.tv_usec = 500;

			nRet = select( 0 , &fdRead , NULL , NULL , &TimeVal );
			if( SOCKET_ERROR == nRet )
			{
				g_LastError = ERROR_SELECT;
				UpdateLogFile( "Select失败!" );
//				TRACE( "select 错误\r\n" );
				Sleep( 100 );
				continue;
			}

			if( nRet == 0 )
			{
				Sleep( 100 );
				continue;
			}

			//接收数据
			lFrameLen = 48;
			lOffset = 0;
			while( lFrameLen > 0 )
			{//循环读取数据
				nRet = recv( pThreadContext->ConnSocket , Buffer+lOffset , lFrameLen , 0 );
				if( SOCKET_ERROR == nRet || 0 == nRet )
				{
					UpdateLogFile( "本次连接在接收数据时出错!" );
//					TRACE( "本次连接在接收数据时出错\r\n" );
					closesocket( pThreadContext->ConnSocket );
					break;
				}
				lFrameLen -= nRet ;
				lOffset += nRet;
			}
			if( lFrameLen > 0 )
			{//数据没有正确的读到
				break;
			}

			//记录本地时间T2
			GetSystemTime( &SystemTime );
			SystemTimeToFileTime( &SystemTime , (FILETIME*)&T2 ); 
			//判断数据包的正确性
			if( Buffer[0] != 0x1B )
			{
				UpdateLogFile( "接收的数据错误!" );
//				TRACE( "接收的数据错误\r\n" );
				closesocket( pThreadContext->ConnSocket );
				break;
			}

			//填充数据包
			memcpy( (char*)&Buffer[32] , (char*)&T2 , sizeof( LONGLONG ) ); 
			Buffer[0] = 0x1C;

			//取本地时间T3
			GetSystemTime( &SystemTime );
			SystemTimeToFileTime( &SystemTime , (FILETIME*)&T3 );
			memcpy( (char*)&Buffer[40] , (char*)&T3 , sizeof( LONGLONG ) );

			//发送数据包
			lFrameLen = 48;
			lOffset = 0;
			while( lFrameLen > 0 )
			{//循环发送数据包
				nRet = send( pThreadContext->ConnSocket , Buffer+lOffset , lFrameLen , 0 );
				if( SOCKET_ERROR == nRet || nRet == 0 )
				{
					UpdateLogFile( "发送数据错误!" );
//					TRACE( "发送数据错误\r\n" );
					closesocket( pThreadContext->ConnSocket );
					break;
				}
				lFrameLen -= nRet;
				lOffset += nRet;

			}

			//结束连接
			closesocket( pThreadContext->ConnSocket );

			break;
		}//while( TRUE )

		//完成任务
		//判断自己是否为临时创建
		if( ID >= MAX_THREAD )
		{
			free( pThreadContext );
			break;
		}
		
	}//while( pThreadContext->isContinue )
	
	free( Buffer );

	if( ID < MAX_THREAD )
		SetEvent( g_ThreadContextList[ID].hEndEvent );

	return 0;
}


BOOLEAN InitServer(void)
{
	WSADATA         wsaData;
	UINT			i = 0;
	ULONG			lThreadID = 0;
	LONG			lRet = 0;
//	HKEY			hKey;
	DWORD			dwLen = 32;
	DWORD			dwType = REG_SZ;

/*
	//取得注册表信息
	lRet = RegOpenKey( HKEY_LOCAL_MACHINE , REG_IPADDR , &hKey );
	if( 0 != lRet )
	{
		printf( "RegOpenKey Failed" );
		MessageBox (NULL, "RegOpenKey失败!", "TimeServer", MB_OK|MB_ICONINFORMATION);
		return FALSE;
	}

	lRet = RegQueryValueEx( hKey , "IpAddr" , NULL , &dwType , g_strIpAddr , &dwLen );
	if( 0 != lRet )
	{
		MessageBox (NULL, "RegQueryValueEx失败!", "TimeServer", MB_OK|MB_ICONINFORMATION);
		return FALSE;
	}

*/

	

	char	szCurrentDir[_MAX_PATH];
//	char	strIpAddr[32];
	UpdateLogFile( "Enter InitServer" );
	memset( g_strIpAddr , 0 , 32 );
	memset( szCurrentDir , 0 , _MAX_PATH );
	GetModuleFileName( NULL , szCurrentDir , _MAX_PATH );
	*strrchr( (char*)szCurrentDir , '\\' ) = '\0';
	strcat( szCurrentDir , "\\config.ini" );

	GetPrivateProfileString( "Info" , "IpAddr" , "127.0.0.1" , g_strIpAddr , 32 , szCurrentDir );

	UpdateLogFile( g_strIpAddr );
	
	//创建多个工作线程
	for( i = 0 ; i < MAX_THREAD ; i ++ )
	{
		g_ThreadContextList[i].hMutex = CreateMutex( NULL , FALSE , NULL );
		if( NULL == g_ThreadContextList[i].hMutex )
		{
			g_LastError = ERROR_MUTEX;
			UpdateLogFile( "创建锁失败!" );
//			TRACE( "创建锁失败\r\n" );
			return FALSE;
		}
		g_ThreadContextList[i].hJobEvent = CreateEvent( NULL , TRUE , FALSE , NULL ) ;
		if( NULL == g_ThreadContextList[i].hJobEvent )
		{
			g_LastError = ERROR_EVENT;
			UpdateLogFile( "创建事件失败!" );
//			TRACE( "创建事件失败\r\n" );
			return FALSE;
		}
		g_ThreadContextList[i].hEndEvent = CreateEvent( NULL , TRUE , FALSE , NULL );
		if( NULL == g_ThreadContextList[i].hEndEvent )
		{
			g_LastError = ERROR_EVENT;
			UpdateLogFile( "创建事件失败!" );
//			TRACE( "创建事件失败\r\n" );
			return FALSE;
		}

		g_ThreadContextList[i].isContinue = TRUE;
		g_ThreadContextList[i].isBusy = FALSE;
		
		if( NULL == CreateThread( NULL , 0 , WorkThread , (LPVOID)i , (DWORD)0 , &lThreadID) )
		{
			g_LastError = ERROR_THREAD;
			UpdateLogFile( "创建线程失败!" );
//			TRACE( "创建线程失败\r\n" );
			return FALSE;
		}

	}//for( i = 0 ; i < MAX_THREAD ; i ++ )

	if( WSAStartup( 0x0002 , &wsaData ) ) 
		return FALSE;

	g_hSocketTimeServer = CreateServiceSocket( inet_addr(g_strIpAddr) , 1025 );

	UpdateLogFile( "Exit InitServer" );

	return g_hSocketTimeServer != INVALID_SOCKET;
}
/****************************************************************************************/
void ReleaseServer(void)
{
	UINT	i = 0;

	//停止多个线程
	for( i = 0 ; i < MAX_THREAD ; i ++ )
	{
		ResetEvent( g_ThreadContextList[i].hEndEvent );
		g_ThreadContextList[i].isContinue = FALSE;
		WaitForSingleObject( g_ThreadContextList[i].hEndEvent , INFINITE );
		CloseHandle( g_ThreadContextList[i].hJobEvent );
		CloseHandle( g_ThreadContextList[i].hEndEvent );
		CloseHandle( g_ThreadContextList[i].hMutex );
	}



	if( g_hSocketTimeServer != INVALID_SOCKET ) 
		closesocket( g_hSocketTimeServer );

	WSACleanup ();
}
/****************************************************************************************/

INT ServerHandler(void)
{
	ULONG				lAddrSize = 0;
	struct timeval		TimeVal;
	fd_set				fdRead;
	SOCKET				ConnSocket;
	SOCKADDR_IN			ClientAddr;
	UINT				i = 0;
	PTHREADCONTEXT		pTempContext = NULL;
	ULONG				lThreadID = 0;

	lAddrSize = sizeof( SOCKADDR );

//	UpdateLogFile( "Enter ServerHandler" );

	TimeVal.tv_sec = 0;
	TimeVal.tv_usec = MUST_WAIT_TIME;

	FD_ZERO( &fdRead );
	FD_SET( g_hSocketTimeServer , &fdRead );
	if( select( 0, &fdRead , NULL , NULL , &TimeVal ) <= 0 )
	{
		Sleep( 50 );
		return 1;
	}

//	UpdateLogFile( "before accept" );
	ConnSocket = accept( g_hSocketTimeServer , (SOCKADDR*)&ClientAddr , &lAddrSize );
//	UpdateLogFile( "after accept" );
	if( INVALID_SOCKET == ConnSocket )
	{
		if( WSAEWOULDBLOCK == WSAGetLastError( ) )
		{
			Sleep( 50 );
			return 1;
		}
		else
		{
			g_LastError = ERROR_ACCEPT;
			UpdateLogFile( "接收连接错误!" );
//			TRACE( "接收连接错误\r\n" );
			return ERROR_ACCEPT;
		}
	}

	for( i = 0 ; i < MAX_THREAD ; i ++ )
	{
		if( !g_ThreadContextList[i].isBusy )
			break;
	}
	if( i < MAX_THREAD )
	{//找到了
		g_ThreadContextList[i].isBusy = TRUE;
		g_ThreadContextList[i].ConnSocket = ConnSocket;
		SetEvent( g_ThreadContextList[i].hJobEvent );
	}
	else
	{//没有找到,创建临时的
		pTempContext = ( PTHREADCONTEXT )malloc( sizeof( THREADCONTEXT ) );

		pTempContext->isContinue = TRUE;
		pTempContext->ConnSocket = ConnSocket;

		if( NULL == CreateThread( NULL , 0 , WorkThread , pTempContext , (DWORD)0 , &lThreadID) )
		{
			g_LastError = ERROR_TEMPTHREAD;
			UpdateLogFile( "创建临时线程失败!" );
//			TRACE( "创建临时线程失败\r\n" );
			return 1;
		}
	}
	return 1;
}


BOOL UpdateLogFile(LPCTSTR szStr)
{
	HANDLE		hFile;
	char		szFileName[_MAX_PATH],szMessage[_MAX_PATH];
	
//	CHAR		szTemp[11];
	CHAR		szCurrentDir[_MAX_PATH];
	char		szFilePath[_MAX_PATH];
	INT			nBytesRet;
	ULONG		lBytesWritten = 0;
	SYSTEMTIME	SystemTime;
	
	memset( szCurrentDir , 0 , _MAX_PATH );
	memset( szFilePath , 0 , _MAX_PATH );
	nBytesRet=GetModuleFileName(NULL,szCurrentDir,_MAX_PATH);
	*strrchr( (char*)szCurrentDir , '\\' ) = '\0';

	memcpy( szFilePath , szCurrentDir , strlen( szCurrentDir ) );
	
	GetLocalTime( &SystemTime );

	sprintf( szFileName , "%d-%d-%d" , SystemTime.wYear , SystemTime.wMonth , SystemTime.wDay );
	strcat(	szFileName , ".log" );

	strcat( szFilePath , "\\" );
	strcat( szFilePath , szFileName );
	
	hFile = CreateFile( szFilePath , 
						GENERIC_READ|GENERIC_WRITE , 
						FILE_SHARE_READ , 
						NULL , 
						OPEN_ALWAYS, 
						FILE_ATTRIBUTE_NORMAL , 
						NULL );
	if( INVALID_HANDLE_VALUE == hFile )
	{
		return FALSE;
	}
	
	sprintf( szMessage , "%d:%d:%d       " , SystemTime.wHour , SystemTime.wMinute , SystemTime.wSecond );
	strcat( szMessage , szStr );
	strcat( szMessage , "\r\n" );

	SetFilePointer( hFile , 0 , NULL , FILE_END );

	WriteFile( hFile , szMessage , strlen( szMessage ) , &lBytesWritten , NULL ); 
	
	CloseHandle( hFile );

	return TRUE;
}

⌨️ 快捷键说明

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