心跳包的线程同步有关问题
心跳包的线程同步问题
本人的心跳包处理是这么设计的,在启动程序后,立刻开启一个心跳线程,专门用于处理客户的连接。这个线程用于处理所有的客户端的连接,当线程没有接到其中一个客户发来的请求达到20秒,即认为掉线。客户连接时,发送了一次数据之后,立刻退出。
为了保证定时处理,启动了可等待定时器与事件机制。
1.心跳线程是这么启动的:
HANDLE hHeatBeat=CreateThread(NULL,0,CHeartBeat::WaitProc,NULL,0,NULL);
CloseHandle(hHeatBeat);
2.心跳包的主线程
本人的心跳包处理是这么设计的,在启动程序后,立刻开启一个心跳线程,专门用于处理客户的连接。这个线程用于处理所有的客户端的连接,当线程没有接到其中一个客户发来的请求达到20秒,即认为掉线。客户连接时,发送了一次数据之后,立刻退出。
为了保证定时处理,启动了可等待定时器与事件机制。
1.心跳线程是这么启动的:
HANDLE hHeatBeat=CreateThread(NULL,0,CHeartBeat::WaitProc,NULL,0,NULL);
CloseHandle(hHeatBeat);
2.心跳包的主线程
- C/C++ code
DWORD CALLBACK CHeartBeat::WaitProc(LPVOID lpVoid) { HANDLE hTimer; BOOL bSuccess; __int64 qwDueTime; LARGE_INTEGER liDueTime; char szError[255]; DWORD dwResult; HANDLE* phTimers=NULL,*phEvents=NULL; while(true) { if(hbList.size()>0) { //manage events phEvents=(HANDLE*)LocalAlloc(LPTR|LMEM_ZEROINIT,sizeof(HANDLE)*hbList.size()); for(vector<CHeartBeat*>::size_type i=0;i<hbList.size();++i) { if(hbList[i]->m_hEvent!=NULL) phEvents[i]=hbList[i]->m_hEvent; } //wait for one of event become signal, if there are no events become sigal,after 500 millisecond, it return dwResult=WaitForMultipleObjects((DWORD)hbList.size(),phEvents,FALSE,500); if(dwResult>=WAIT_OBJECT_0 && dwResult<=WAIT_OBJECT_0+hbList.size()-1) { vector<CHeartBeat*>::iterator iter=hbList.begin(); for (;iter!=hbList.end();++iter) { if((*iter)->m_hEvent==phEvents[dwResult-WAIT_OBJECT_0]) { if((*iter)->m_hTimer!=NULL) { //when follow MCT health messages was recevied CancelWaitableTimer((*iter)->m_hTimer); bSuccess = SetWaitableTimer( (*iter)->m_hTimer, // Handle to the timer object &liDueTime, // When timer will become signaled 1200000, // Periodic timer interval of 2 seconds NULL, NULL, FALSE ); // Do not restore a suspended system if (! bSuccess ) { sprintf( szError, "SetWaitableTimer failed with Error \ %d.\n", GetLastError() ); cout<<szError<<endl; CloseHandle( hTimer ); return false; } } else { if ( hTimer = CreateWaitableTimer( NULL, // Default security attributes FALSE, // Create auto-reset timer NULL ) ) // Name of waitable timer { // Create an integer that will be used to signal the timer // 120 seconds from now. qwDueTime = -20 * _SECOND; // Copy the relative time into a LARGE_INTEGER. liDueTime.LowPart = (DWORD) ( qwDueTime & 0xFFFFFFFF ); liDueTime.HighPart = (LONG) ( qwDueTime >> 32 ); bSuccess = SetWaitableTimer( hTimer, // Handle to the timer object &liDueTime, // When timer will become signaled 1200000, // Periodic timer interval of 120 seconds NULL, NULL, FALSE ); // Do not restore a suspended system if (! bSuccess ) { sprintf( szError, "SetWaitableTimer failed with Error \ %d.\n", GetLastError() ); cout<<szError<<endl; CloseHandle( hTimer ); return false; } (*iter)->m_hTimer=hTimer; } else { sprintf( szError, "CreateWaitableTimer failed with Error \ %d.\n", GetLastError() ); cout<<szError<<endl; return false; } } ResetEvent((*iter)->m_hEvent); } } } else if(dwResult==WAIT_FAILED) { OutputDebugString(_T("wait event singal failed\n")); } LocalFree((HLOCAL)phEvents); //manage waitable timers phTimers=(HANDLE*)LocalAlloc(LPTR|LMEM_ZEROINIT,sizeof(HANDLE)*(hbList.size())); for(vector<CHeartBeat*>::size_type i=0;i<hbList.size();++i) { if(hbList[i]->m_hTimer!=NULL) phTimers[i]=hbList[i]->m_hTimer; } //wait for one of event become signal, if there are no events become sigal,after 500 millisecond, it return DWORD dwResult=WaitForMultipleObjects((DWORD)(hbList.size()),phTimers,FALSE,500); if(dwResult>=WAIT_OBJECT_0 && dwResult<=WAIT_OBJECT_0+hbList.size()-1) { //a client is power off vector<CHeartBeat*>::iterator iter=hbList.begin(); int i=0; for (;iter!=hbList.end();++iter) { i++; if((*iter)->m_hTimer==phTimers[dwResult-WAIT_OBJECT_0]) { CHeartBeat* phb=(*iter); char mbProjNum[1024]; strcpy(mbProjNum,phb->m_strProj); printf("\na power off event occuered on ProjNum:%s\n",mbProjNum); //before remove element, clear event and timer SetEvent((*iter)->m_hEvent); WaitForSingleObject((*iter)->m_hEvent,INFINITE); CloseHandle((*iter)->m_hEvent); CloseHandle((*iter)->m_hTimer); //remove element hbList.erase(iter); break; } } } LocalFree((HLOCAL)phTimers); } //#region 1 //heart beat thread will exist if(WaitForSingleObject(m_hExitHandle,500)==WAIT_OBJECT_0) { if(hbList.size()>0) { vector<CHeartBeat*>::iterator iter=hbList.begin(); for(;iter!=hbList.end();++iter) { CHeartBeat* pHB=(CHeartBeat*)(*iter); if(pHB->m_hEvent!=NULL) { CloseHandle(pHB->m_hEvent); SetEvent(pHB->m_hEvent); WaitForSingleObject(pHB->m_hEvent,INFINITE); } if(pHB->m_hTimer!=NULL) { CancelWaitableTimer(pHB->m_hTimer); CloseHandle(pHB->m_hTimer); } SAFE_DELETE(pHB); } hbList.clear(); break; } } //#endregion } return true; }