心跳包的线程同步问题

paerxiushi 2008-11-08 03:07:14
加精
本人的心跳包处理是这么设计的,在启动程序后,立刻开启一个心跳线程,专门用于处理客户的连接。这个线程用于处理所有的客户端的连接,当线程没有接到其中一个客户发来的请求达到20秒,即认为掉线。客户连接时,发送了一次数据之后,立刻退出。
为了保证定时处理,启动了可等待定时器与事件机制。
1.心跳线程是这么启动的:
HANDLE hHeatBeat=CreateThread(NULL,0,CHeartBeat::WaitProc,NULL,0,NULL);
CloseHandle(hHeatBeat);

2.心跳包的主线程

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;
}



3.当有客户连接时,向心跳线程发送事件信号,对于客户每一次连接,服务端会创建一个心跳包对象,将其加入列表,而当客户后序连接时,服务端仅设置指定的事件信号

bool bExist=false;
CHeartBeat* pHeartBeat=NULL;
for(vector<CHeartBeat*>::iterator iter=hbList.begin();
iter!=hbList.end();
++iter)
{
if(strcmp((*iter)->GetProjNum(),pMessageInfo->msg_base_info.szPlanNumber)==0)
{
//IM has received health message previous for special plannumber
bExist=true;
pHeartBeat=*iter;
break;
}
}
if(bExist)
{
//notify CHeartBeat to reset waitable timer
if(pHeartBeat!=NULL) SetEvent(pHeartBeat->GetEventHandle());
return true;
}
else
{
CHeartBeat* pHeart=new CHeartBeat();
//notify CHeartBeat to create waitable timer
if(!pHeart->Start(pMessageInfo->msg_base_info.szPlanNumber))
{
SAFE_DELETE(pHeart);
return false;
}

hbList.push_back(pHeart);
return true;

}
return true;


3.以下是CHeartBeat类的Start方法:

bool CHeartBeat::Start(const char* projNum)
{
HANDLE handle;
handle=CreateEvent(NULL,TRUE,FALSE,NULL);

if(handle==NULL)
{
return false;

}
m_hEvent=handle;
SetEvent(m_hEvent);
strcpy(m_strProj,projNum);
return true;
}


4.当有服务端结束时,等待心跳线程退出
HANDLE hExitHeartBeat=CreateEvent(NULL,TRUE,TRUE,NULL);
CHeartBeat::SetExitEvent(hExitHeartBeat);
WaitForSingleObject(hHeatBeat,INFINITE);, (1)
对于心跳线程的退出处理用代码段2中的region 1

请问各位大侠,为什么当服务端运行到WaitForSingleObject(hHeatBeat,INFINITE)时,这个函数无法返回,而且心跳线程明明可以已经退出了。
当把语句(1)修改成WaitForSingleObject(hHeatBeat,1000);时
程序有时候会内存泄露?
...全文
3030 45 打赏 收藏 转发到动态 举报
写回复
用AI写文章
45 条回复
切换为时间正序
请发表友善的回复…
发表回复
zwd602 2011-12-22
  • 打赏
  • 举报
回复
学习了,厉害,好好吃透你的,变为己用啊
lrboy 2010-11-05
  • 打赏
  • 举报
回复
MARK
longren331100 2010-10-25
  • 打赏
  • 举报
回复
心跳不好搞啊
wuleiwuhen 2010-07-28
  • 打赏
  • 举报
回复
我现在在做有关心跳的,不甚懂呀。
usr33322 2009-12-09
  • 打赏
  • 举报
回复
软件架构QQ群 群号76395176

软件架构,UML,开发语言不限,架构是主题,软件一般问题也鼓励讨论,情感交流


工作经验5年以上,年令30以上
ahead_8 2009-12-01
  • 打赏
  • 举报
回复
mark
joycl 2009-03-09
  • 打赏
  • 举报
回复
好好学习一下····
xiaoyunchen 2009-02-27
  • 打赏
  • 举报
回复
有没有JAVA实现的
hungyuen 2009-02-15
  • 打赏
  • 举报
回复
mark ..mark
Fred_Mark 2008-12-05
  • 打赏
  • 举报
回复
学习,接分:)
konta 2008-12-05
  • 打赏
  • 举报
回复
mark.......................
fengwanzk 2008-12-05
  • 打赏
  • 举报
回复
不甚懂,学习一下。
CCppMfc 2008-12-05
  • 打赏
  • 举报
回复
a
nizhaorong 2008-12-04
  • 打赏
  • 举报
回复
看看这本书Win32多线程程序设计(侯捷),里面有更为详细的讲解。


http://www.erpside.cn/forumdisplay.php?fid=44
http://www.erpside.cn/forumdisplay.php?fid=45
nizhaorong 2008-12-04
  • 打赏
  • 举报
回复
看看这本书Win32多线程程序设计(侯捷),里面有更为详细的讲解。

各位帮我顶顶这里:
http://www.erpside.cn/forumdisplay.php?fid=44
http://www.erpside.cn/forumdisplay.php?fid=45
fxltsblsds 2008-12-04
  • 打赏
  • 举报
回复
111111111111
gouwa20080808 2008-12-04
  • 打赏
  • 举报
回复
支持
cs_iceworld 2008-12-04
  • 打赏
  • 举报
回复
mark
sam_zx2008 2008-12-04
  • 打赏
  • 举报
回复
mark , study ~
wangkeyunanjing 2008-12-03
  • 打赏
  • 举报
回复
good good csdn day day UP
加载更多回复(25)

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧