1.通信端口封装
实现串口、UDP、TCP的封装
UML类图:
源码下载:http://pan.baidu.com/s/1gdOIOnh
调用示例:
<span style="font-size:18px;"><span style="font-size:18px;"> if (pDevice->GetComType() == 0)//串口通信方式
{
if(pDevice->GetAutoReceive()) //主动上报
m_pPortManage = new CComPortManage(this, pDevice->GetComPort(), pDevice->GetBaudrate());
else //请求上报
m_pPortManage = new CComPortManage(pDevice->GetComPort(), pDevice->GetBaudrate());
}
else if (pDevice->GetComType() == 1)//TCP通信方式
{
if(pDevice->GetAutoReceive()) //主动上报
m_pPortManage = new CTcpManage(this, pDevice->GetComPort(), pDevice->GetBaudrate());
else //请求上报
m_pPortManage = new CTcpManage(pDevice->GetComPort(), 5009);
}
else if//UDP通信方式
{
if (psubSystem->GetComType() == 1)//主动上报
m_pPortManage = new CUDPManage(this, psubSystem->GetNetIP(), psubSystem->GetNetSendPort(), psubSystem->GetNetRecPort());
else//请求上报
m_pPortManage = new CComPortManage(this, psubSystem->GetNetIP(), psubSystem->GetNetSendPort());
}</span></span>
2.多任务并发处理
并发处理,采用生产者-消费者模型,本项目使用单生产者-多消费者模型:
生产者:接收来自前端的UDP数据包,并加入任务队列,唤醒消费者线程处理任务。
创建task:
<span style="font-size:18px;">bool CChannelManager::ReceiveChannelInfo(LONG lSessionID)
{
///接收数据处理
BYTE inBuf[DATALENGHT] = {0x0};
int inBufLen = 0;
char sSpecialData[21] = {0x0};
int nReplyPort = 0;
char sendIp[20] = {0x0};
if (UDP_RecBuf(inBuf, inBufLen, sSpecialData, nReplyPort, sendIp,lSessionID))
{
TRACE(_T("%sRec:%s\r\n"),sendIp,inBuf);
CDataManager::Instance().SaveLogFile((char*)inBuf,_T("RecDataLog.txt"));
m_pTaskManager->CreateTask(inBuf, inBufLen, sSpecialData, nReplyPort, sendIp, lSessionID);
return true;
}
return false;
}</span>
<span style="font-size:18px;">// 增加task
void CTaskManager::CreateTask(LPBYTE inBuf,
int inBufLen,
LPSTR sSpecialData,
int nReplyPort,
LPSTR sendIp,
LONG lSessionID)
{
CSingleLock lock(&m_csCommunicationSync, TRUE);
char outbuf[SQLLENGHT] = {0x0};
int noutlen = 0;
int nindex = 1;
bool bLocalExecute = true;
while(CTaskManager::ParseTask((const char *)inBuf,inBufLen,outbuf,noutlen,nindex,'{','}'))
{
if (nindex == 1) //解析第一个包,判断是否继续解包
{
long lOrgType = 0; // 所属机构类型
long lOrgID = 0; // 所属机构编号
long lDeviceType = 0; // 设备类型
long lDeviceID = 0; // 设备编号
int nEvent = 0;
int ncommunicateType = 0;
int noutFlag = 0;
char outProbuf[SQLLENGHT] = {0x0};
int noutProlen = 0;
if(!CTask::ParseProtocol((const char*)outbuf, noutlen, outProbuf, noutProlen,nEvent,noutFlag,ncommunicateType, lOrgType,lOrgID,lDeviceType,lDeviceID))
{
return;
}
if (nEvent == 6) //下发下级组态
{
if (noutFlag == 0 || //监控工作站发送
(noutFlag == 1 && !CDataManager::Instance().DownOrderIsLocalExecute(lOrgType,lOrgID))) //上级通信组态发送但不在本级执行
{
CTask *pTask = new CTask();
memcpy_s(pTask->m_sRecvBuffer,inBufLen,inBuf,inBufLen);
pTask->m_inBufLen = inBufLen;
memcpy_s(pTask->m_sSendIp,20,sendIp,20);
memcpy_s(pTask->m_sSpecialData,25,sSpecialData,25);
pTask->m_nReplyPort = nReplyPort;
pTask->m_bLocalExecute = false;
m_TaskList.AddTail(pTask);
break;
}
}
}
CTask *pTask = new CTask();
memcpy_s(pTask->m_sRecvBuffer,noutlen,outbuf,noutlen);
pTask->m_inBufLen = noutlen;
memcpy_s(pTask->m_sSendIp,20,sendIp,20);
memcpy_s(pTask->m_sSpecialData,25,sSpecialData,25);
pTask->m_nReplyPort = nReplyPort;
pTask->m_bLocalExecute = true;
m_TaskList.AddTail(pTask);
memset(outbuf,0x0,SQLLENGHT);
noutlen = 0;
++nindex;
}
SetEvent(m_hReadEvent);
}</span>
消费者:在初始化时被创建消费者,等待生产者唤醒做任务。做任务时从任务队列取任务,并处理任务,等待下一次唤醒。
<span style="font-size:18px;">//task manage
UINT CTaskManager::TaskManageThreadProc(void * lParam)
{
DWORD Event = 0;
CTaskManager *pTaskManager = (CTaskManager *)lParam;
pTaskManager->m_bThreadAlive = true;
while(true)
{
Event = WaitForMultipleObjects(2, pTaskManager->m_hArrayEvent, FALSE, INFINITE);
switch(Event)
{
case WAIT_TIMEOUT:
break;
case WAIT_FAILED:
CloseHandle(pTaskManager->m_hTaskManageThread);
pTaskManager->m_hTaskManageThread = NULL;
pTaskManager->m_bThreadAlive = false;
AfxEndThread(0,FALSE);
return 1;
default:
{
if (Event - WAIT_OBJECT_0 == 0)
{
CloseHandle(pTaskManager->m_hTaskManageThread);
pTaskManager->m_hTaskManageThread = NULL;
pTaskManager->m_bThreadAlive = false;
ResetEvent(pTaskManager->m_hExitEvent);
AfxEndThread(0,FALSE);
return 0;
}
if (Event - WAIT_OBJECT_0 == 1)
{
ResetEvent(pTaskManager->m_hReadEvent);
pTaskManager->ScheduleTask();
}
}
break;
}
}
CloseHandle(pTaskManager->m_hTaskManageThread);
pTaskManager->m_hTaskManageThread = NULL;
pTaskManager->m_bThreadAlive = false;
AfxEndThread(0,FALSE);
return 1;
}</span>
关于生产者-消费者模型,另可参考本博客文章:http://blog.csdn.net/ceasadan/article/details/50469647