Console方式的通信服務
好久沒有采用Console方式寫程序了,以前做項目如果用C++,也多采用MFC ,WTL等一些界面框架來做,記得用Console來做應用還是在剛畢業那會兒用C++寫寫演示程序什麼的,僅供學習之用了。最近採用C++寫了一個校園RFID信息接入的一個接口服務器,通過RFID接收設備獲取掃描到的RFID卡信息,然後上傳到數據庫,供上層應用來使用。系統的結構大致如下面這個圖。
RFID接收設備採用UDP報文上傳掃描到的RFID卡信息;
Socket庫初始化如下:
int nRetCode = 0 ;
WSADATA wsaData ;
WORD wVersionRequested = MAKEWORD( 1, 1 );
int err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
return 0 ;
}
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
WSACleanup( );
return 0 ;
}
Socket初始化,綁定UDP端口
_sockSrv=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(32500);
bind(_sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
然後啓動一個單獨的線程接收UDP報文
_hThread = CreateThread( NULL , NULL , ProcessRFID , &_sockSrv ,NULL , &dwThread ) ;
線程函數處理接收數據,判斷有效性,並處理接收到的報文
SOCKET sockSrv = *(SOCKET *)lpVoid ;
UCHAR buffer[MAX_BUFFER] = {0} ;
SOCKADDR_IN addrClient;
int addrLen=sizeof(SOCKADDR);
while(1)
{
int iLen = recvfrom( sockSrv ,(CHAR *)buffer , MAX_BUFFER , 0 , (sockaddr *)&addrClient , &addrLen ) ;
if( iLen == 0 || iLen == SOCKET_ERROR)
{
return -1;
}
//////////////////////////////////////////////////////////////////////////
//解析報文開始
if( !ValidRFidPacket(buffer , iLen ))
{
return -1 ;
}
HandleRFidPacket(buffer , iLen ) ;
}
這裏注意,當關閉Console窗口的時候,需要後續的清理動作
所以在初始化的時候,還需要補充設置一下事件回調
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ;
回調函數內容調用ExitProcess做退出清理
BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType )
{
case CTRL_CLOSE_EVENT:
ExitProcess() ;
return( TRUE );
case CTRL_LOGOFF_EVENT:
ExitProcess() ;
return FALSE;
case CTRL_SHUTDOWN_EVENT:
ExitProcess() ;
return FALSE;
default:
return FALSE;
}
}
運行後截圖
採用Console方式做的通信服務器,信息查看採用命令行就行了,界面不需要耗費過多的資源,運行還是比較穩定的。運行起來佔用的內存基本不會有變化,長時間運行性能更穩定。