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方式做的通信服务器,信息查看采用命令行就行了,界面不需要耗费过多的资源,运行还是比较稳定的。运行起来占用的内存基本不会有变化,长时间运行性能更稳定。