//设置KeepAlive
BOOL   bKeepAlive   =   TRUE;
nRet   =   ::setsockopt(m_sockDesc,   SOL_SOCKET,   SO_KEEPALIVE,   (char*)&bKeepAlive,   sizeof(bKeepAlive));
if   (nRet   !=0)
{
sprintf(m_pszError,   "Winsock   error   :   %s   (Error   Code   %d)\n ",   "Socket   SetOpt   failed ",   WSAGetLastError());
return   FALSE;
}//设置KeepAlive检测时间和次数
TCP_KEEPALIVE   inKeepAlive   =   {0};   //输入参数
unsigned   long   ulInLen   =   sizeof(TCP_KEEPALIVE);    TCP_KEEPALIVE   outKeepAlive   =   {0};   //输出参数
unsigned   long   ulOutLen   =   sizeof(TCP_KEEPALIVE);    unsigned   long   ulBytesReturn   =   0;//设置socket的keep   alive为10秒,并且发送次数为3次
inKeepAlive.onoff   =   1;  
inKeepAlive.keepaliveinterval   =   10000;   //两次KeepAlive探测间的时间间隔
inKeepAlive.keepalivetime   =   3;   //开始首次KeepAlive探测前的TCP空闭时间nRet   =   WSAIoctl(m_sockDesc,  
SIO_KEEPALIVE_VALS,
(LPVOID)&inKeepAlive,
ulInLen,
(LPVOID)&outKeepAlive,
ulOutLen,
&ulBytesReturn,
NULL,
NULL);
if(SOCKET_ERROR   ==   nRet)
{
sprintf(m_pszError,   "Winsock   error   :   %s   (Error   Code   %d)\n ",   "Nonblocking   socket   call   error ",   WSAGetLastError());
return   FALSE;
}这是一段设置系统默认心跳包的代码,有一点不太清楚。这么处理心跳包的返回。当心跳包探测到对方不在了(如何判断),我想做一些自己定义的动作,这些动作我应该写到什么地方。

解决方案 »

  1.   

       其实我觉得心跳包不用弄得那么复杂.创建一个线程.隔上几秒把所有的socket句柄都取出来看能不能发送一个空数据.如果发送成功,就说明socket还有效,否则就说明断掉了..很简单...我就这样子做的...
      

  2.   

    失去客户端来连接函数GetQueuedCompletionStatus会返回FALSE。
    if(GetQueuedCompletionStatus(CompletionPort, BytesTransferred,DWORD(PerHandleData),
    POverlappe(PerIoData),INFINITE) = FALSE)
    {
        //这里处理断线
    }
      

  3.   

    所谓的心跳包就是在客户端和服务器端间定时通知对方自己状态的一个自己定义的命令字,按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。         一般是用来判断对方(设备,进程或其它网元)是否正常动行,一般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉。用于检测TCP的异常断开。        基本原因是服务器端不能有效的判断客户端是否在线也就是说,服务器无法区分客户端是长时间在空闲,还是已经掉线的情况.所谓的心跳包就是客户端定时发送简单的信息给服务器端告诉它我还在而已。        代码就是每隔几分钟发送一个固定信息给服务端,服务端收到后回复一个固定信息
    如果服务端几分钟内没有收到客户端信息则视客户端断开。比如有些通信软件长时间不使用,要想知道它的状态是在线还是离线就需要心跳包,定时发包收包。        发包方:可以是客户也可以是服务端,看哪边实现方便合理。一般是客户端。服务器也可以定时轮询发心跳下去。
            一般来说,出于效率的考虑,是由客户端主动向服务器端发包,而不是相反。         心跳包是用户数据包,与协议无关,所以会发送数据就会发送心跳包,格式自定义。 
            心跳包也可以用来占领住IP资源,达到永远在线的目的。 
            比如:在移动上网时,IP是一种有限的紧张的资源,电信会把已分配的但长时间未使用的IP回收回来,所以要发心跳包告诉电信,我的IP仍然在使用中。
      

  4.   

    每个连接最后一次通信的时间到现在超过间隔就发个心跳过去,过会再去看看他有没有回应,没回应就是不在线了。
    -----------------------------------------------
    http://www.wantsoft.com
    隐形者软件代码交流博客
    -----------------------------------------------
      

  5.   

    服务端开一个新的线程,然后使用CreateWaitableTimer创建可等待定时器,当有HEALTH消息过来,就用SetWaitableTimer刷新定时器的信号,当用WaitForSingleObject函数有信号过来了,说明客户端已下线,主线程就可以关闭连接。
    注意:心跳线程可以处理所有客户端的连接。
      

  6.   

    将SetWaitableTimer中第二个参数设置为等待多少秒之后,判断客户端已断。
      

  7.   

    参见我发的贴子:
    http://topic.csdn.net/u/20081108/15/cf8db1e7-8a9c-4e2c-9472-440cce8babec.html
      

  8.   

    paerxiushi,你的处理程序怎么不是很明白呀!
      

  9.   

    心跳包的处理需要启动一个新线程,这个线程需要管理三类核心对象:
    1.每个客户端上线时,发出的事件m_hEvent
    2.接受到客户连接请求时,开启一个定时器m_hTimer
    3.主线程退出时,通知心跳线程退出事件的m_hExitEvent;
    4.客户列表(包含每个客户的事件,等待定时器,ProjNum),ProjNum对于每个客户地址当有第一个客户上线时,定时一个事件m_hEvent,然后启动心跳线程,在心跳线程中使用WaitForMutiplyObjects等待事件变成信号的,
    当事件有信号时,使用CreateWaitableTimer创建定时器,然后再使用SetWaitableTimer来设置定时器。
    当有客户第二个发送消息时,会再设置m_hEvent为信号状态,这时心跳线程使用Waitfor返回后,使用SetWaitableTimer刷新定时器的等待时间,那么等待时间重新变成30秒
    当某个客户过了30秒还没有发消息过来,就定时器会变成信号态的,这时心咣线程使用WaitForMutiplyObjects等待定时器会返回一个定时器索引,之后心跳线程会移除客户列表中某个成员
    当有客户下线时,会发送一个特定消息,心跳线程处理这个消息时,直接将某个客户从列表中移除。
    当所有客户都下线时,主线程使用m_hExitEvent通知心跳线程来关闭自身注意:我这个示例中没有心跳线程向客户端回发消息的处理,添加时需要在接收到m_hEvent之后回发消息。
    WaitForMutiplyObjects最多接收64个客户,如果有更多客户上线时,需要当客户列表分段来循环等待。
      

  10.   

    paerxiushi,你的方法最终还是没有看懂,但是还是十分感谢你的帮助和热心。问题我自己想了一个解决解决方法,我是在accept后,使用了系统默认的心跳包,同时创建了一个服务线程,这个线程负责所有的接收包,这样就可以ok了。