IO完成模型中如何判断对方断线或非正常关闭? (拔网线)

 IO完成模型中如何判断对方断线或非正常关闭?

经测试,如果没有消息来往,也就是说没有调用过WSARecv(...),WSASend(...)   的话,GetQueuedCompletionStatus(...)这个函数是检测不到拔网线这个动作的(应该是能检测到客户端正常和异常关闭),所以根本不能知道对方是否掉线,还是老老实实用心跳吧。
楼主zhujianping_es(DavidRipple) 2004-11-20 18:42:55 在 VC/MFC / 网络编程 提问

我用IO完成模型WSARecv(...),WSASend(...)  
  与客户端收发数据,但如果客户端非正常关闭  
  (网络不通了或是异常关闭)  
  GetQueuedCompletionStatus(...)会将将相关的  
  WSARecv(...),WSASend(...)返回么??  
  如何判断是对方正常关闭还是断线等情况??  
   
  我现在用IO完成模型,在网上Download了一个类  
  CompletionPortModel   ,感觉还可以,但是它的那个  
  是不保持连接的,我现在需要在服务端保留每个客户的  
  连接(Client   login   to   the   Server   using   Account/Password)  
  于是需要在客户端Connection断掉的时候,在服务端释放  
  相关资源(PER_HANDLE_CONTEXT,CUser.....)  
  如何判断??  
  问题点数:200、回复次数:72Top

1 楼zhujianping_es(DavidRipple)回复于 2004-11-21 17:51:36 得分 0

UP!  
  怎么判断与对方的连接是否中断呀??  
   
  我的服务器需要Keep   connection   with   Client,除非客户端关闭连接或网络不通Top

2 楼zhujianping_es(DavidRipple)回复于 2004-11-21 17:57:55 得分 0

Oh,come   on!  
  Help   pleaseTop

3 楼oyljerry(【勇敢的心】→ ㊣提拉米苏√㊣)回复于 2004-11-21 18:04:03 得分 20

按TCP,正常关闭,会发送fin包,通过四次握手,断开连接  
  非正常退出,就会可能让服务端无法得到,按TCP,需要实现一个保活定时器,来发送heartbeat包保持连接,你也可以通过客户端来发送这个  
  Top

4 楼danyueer(淡月儿:从此以后,各人得各人的眼泪罢了)回复于 2004-11-21 20:51:53 得分 10

我的经验是无需多虑,GetQueuedCompletionStatus()会返回一个错误,判断一下就可以了。Top

5 楼PiggyXP(【小猪】技术太差没脸上班,只好去念Ph.D了-_-b)回复于 2004-11-21 22:22:24 得分 30

请问淡月儿,为什么无需多虑呢?   非正常退出的socket是没有办法用GetQueuedCompletionStatus()获得它的状态的啊?  
   
  我觉得服务器每隔一段时间通过发送心跳包来查询客户端的连接情况比较好,但是会额外增加服务器的负担  
   
  当然正常断开的情况下直接用GetQueuedCompletionStatus()判断就好了,当然也包括WSARecv和WSASend的通知Top

6 楼zhujianping_es(DavidRipple)回复于 2004-11-22 18:13:54 得分 0

I   Use   the   proposed   schema:  
  when   calling  
  WSARecv(....)   /WSASend(....)  
  (SOCKET_ERROR==nResult)   &&   (ERROR_IO_PENDING   !=   WSAGetLastError())  
   
  when    
  bSuccess   =   GetQueuedCompletionStatus(  
  pThis->m_hCOP,  
  &dwNumberBytes,  
  (LPDWORD   )&lpHandleContext,  
  &lpOverlapped,  
  INFINITE  
  );  
  if((!bSuccess)   ||   (bSuccess   &&   (0   ==   dwNumberBytes)))    
  当客户端正常关闭时是可以的,但客户端异常关闭比如  
  客户端网络断开,客户端重启系统  
  服务端用上面的方案就不能得到相关的通知。  
   
   
  Top

7 楼bdove(鸽子情缘)回复于 2004-11-22 18:17:52 得分 0

markTop

8 楼zhujianping_es(DavidRipple)回复于 2004-11-22 18:38:33 得分 0

(1)  
  如果“服务器每隔一段时间通过发送心跳包来查询客户端的连接情况”  
  那么服务器是否这样调用:  
  for   each   user   in   OnlineUserList  
            get   user   connection   socket   handle  
            WSASend(...)  
            if((SOCKET_ERROR==nResult)   &&   (ERROR_IO_PENDING   !=   WSAGetLastError())  
            {  
                          closesocket(....)  
                          recycle   buffer   for   this   IO   operation  
            }  
  end   for  
  如果这样的话,在对掉线的客户端调用  
  WSASend()时,是否就会立即返回  
  (SOCKET_ERROR==nResult)   &&   (ERROR_IO_PENDING   !=   WSAGetLastError())  
  的结果呢??  
   
  (2)  
  如果WSASend调用的返回是那样,那么以前我们对客户端调用的WSARecv(....)没有通过GetQueuedCompletionStatus()  
  返回,在我们对掉线的客户端调用了closesocket(..)后,该WSARecv(...)是否会通过  
  GetQueuedCompletionStatus(....)以   bSuccess   &&   (0   ==   dwNumberBytes)))   的方式返回呢?Top

9 楼zhujianping_es(DavidRipple)回复于 2004-11-22 19:26:57 得分 0

我的应用主要是用户登陆,用户注销,用户修改密码(涉及数据库),发送通知消息,  
  服务器向客户端发送文件,服务端处理用户对文件的处理结果  
  我现在用完成模型,只用了一个完成线程来出来所有的逻辑处理。  
  没有用包队列和专用的包处理线程!!  
  客户端不是很多<400,但要发送文件和数据库查找,修改。一个完成线程可以么???Top

10 楼sharkhuang(走吧走吧!人总会慢慢长大~)回复于 2004-11-22 19:45:02 得分 10

heatbeat估计是唯一办法Top

11 楼zhujianping_es(DavidRipple)回复于 2004-11-22 19:51:06 得分 0

UpTop

12 楼zhujianping_es(DavidRipple)回复于 2004-11-22 21:11:07 得分 0

UpTop

13 楼netgm(问题多多)回复于 2004-11-23 08:19:47 得分 10

客户端不是很多<400,但要发送文件和数据库查找,修改。一个完成线程可以么???  
   
  一般怎么说了..都多线程Top

14 楼zhujianping_es(DavidRipple)回复于 2004-11-23 18:31:29 得分 0

UpTop

15 楼Kendiv(自由蚂蚁 with SP4)回复于 2004-11-23 19:43:19 得分 20

int                                           bSuccess;  
  DWORD                                       dwNumBytes;  
  PER_HANDLE_DATA*                 perHandleData   =   NULL;  
  OVERLAPPED*                           ol                         =   NULL;  
  PER_IO_OPERATION_DATA*     pContext             =   NULL;  
   
  bSuccess   =   GetQueuedCompletionStatus(hCompPort,   &dwNumBytes,   (DWORD*)&perHandleData,   &ol,INFINITE);  
   
  pContext   =   CONTAINING_RECORD(ol,   PER_IO_OPERATION_DATA,   Overlapped);  
   
  if   (   (ERROR_SUCCESS   ==   bSuccess)   ||   (   pContext   !=   NULL   &&   dwNumBytes   ==   0   )   )  
  {  
  //此时,客户端的机器或者重新启动,或者客户端程序异常退出  
  }Top

16 楼Kendiv(自由蚂蚁 with SP4)回复于 2004-11-23 19:45:31 得分 10

上述代码在我设计的网络通讯组件中测试正常。没有必要专门对客户端进行心跳检查。Top

17 楼Kendiv(自由蚂蚁 with SP4)回复于 2004-11-23 19:46:23 得分 10

if   (   (ERROR_SUCCESS   ==   bSuccess)   ||   (   pContext   !=   NULL   &&   dwNumBytes   ==   0   )   )  
  {  
  //此时,客户端的机器或者重新启动,或者客户端程序异常退出  
                    //在此处进行资源释放  
  }  
  Top

18 楼zhujianping_es(DavidRipple)回复于 2004-11-23 19:49:48 得分 0

if   (   (ERROR_SUCCESS   ==   bSuccess)   ||   (   pContext   !=   NULL   &&   dwNumBytes   ==   0   )   )  
  {  
  //此时,客户端的机器或者重新启动,或者客户端程序异常退出  
  }  
   
  在客户端程序异常退出时得不到  
   
  Top

19 楼Kendiv(自由蚂蚁 with SP4)回复于 2004-11-23 19:51:38 得分 10

不好意思,写错了。try   this:  
   
  if   (   (ERROR_SUCCESS   ==   bSuccess)   &&   (   pContext   !=   NULL   &&   dwNumBytes   ==   0   )   )  
  {  
  //此时,客户端的机器或者重新启动,或者客户端程序异常退出  
  }Top

20 楼gdy119(夜风微凉)回复于 2004-11-24 13:29:54 得分 30

如突然拔掉网线,能收到通知吗?   好象不可以吧?  
    发心跳包才是明智之举Top

21 楼hjunxu(hjun)回复于 2004-11-24 14:34:57 得分 30

好象只有心跳可以实现吧,网络故障是不可控的,没有其他办法。Top

22 楼hjunxu(hjun)回复于 2004-11-24 14:46:25 得分 10

--------------------------------------------------------------------------  
  我的应用主要是用户登陆,用户注销,用户修改密码(涉及数据库),发送通知消息,  
  服务器向客户端发送文件,服务端处理用户对文件的处理结果  
  我现在用完成模型,只用了一个完成线程来出来所有的逻辑处理。  
  没有用包队列和专用的包处理线程!!  
  客户端不是很多<400,但要发送文件和数据库查找,修改。一个完成线程可以么???  
  ---------------------------------------------------------------------  
  建议开个线程池,一个线程处理好象不太好。Top

23 楼tangrh(阿唐)回复于 2004-11-24 16:53:15 得分 0

楼上各位,我的解决方案如下:  
          针对每个连接,始终保持一个wsarecv的调用(有且仅有一个),不要收太多数据(太多好资源),这时,如果客户端断掉,那么GetQueuedCompletionStatus马上就可以得到通知  
          winsock2扩展中,同时对一个套接字又收又发是可以的Top

24 楼Hellboy(int argc, char* argv[])回复于 2004-11-24 17:21:47 得分 0

to:tangrh(阿唐)    
  如果客户端拔掉网线,GetQueuedCompletionStatus是不会返回的。  
  除非发送了至少一串数据给客户端,GetQueuedCompletionStatus才会返回出错。Top

25 楼zhujianping_es(DavidRipple)回复于 2004-11-24 20:30:31 得分 0

我用一个链表记录服务器中的所有  
  PER_HANDLE_CONTEXT(就是IO   Completion   Port中的“完成键”)  
  struct   tagPER_HANDLE_CONTEXT   *plstConnection;  
   
  struct   tagPER_HANDLE_CONTEXT  
  {  
        SOCKET   sock;  
        struct   tagPER_HANDLE_CONTEXT   *pNext;    
        struct   tagPER_IO_CONTEXT       *pIoList;  
  }  
  struct   tagPER_IO_CONTEXT  
  {  
      WSAOVERLAP   ol;  
      char       buffer[4096];  
      WSABUF   wsa;  
      tagPER_IO_CONTEXT   *pNext;  
  }  
  并在每个PER_HANDLE_CONTEXT中记录这个SOCKET中的所有的IO_Pending的操作,  
  然后,服务器用一个定时器,每隔1分钟向系统中的每个SOCKET发送心跳包,然后在下次再发  
  heart   beat包时如果发现客户端没有返回相应的反馈包就把这个SOCKET相关的资源释放调!  
  这个都容易,但有一个问题:  
  因为所有的PER_IO_CONTEXT都是通过new或是再ProcessHeap中拿来的,在  
  WSASend()   WSARecv()传递给系统之后,对方系统挂掉了,我们必须回收相关的PER_IO_CONTEXT  
  我们在closesocket()后能够直接delete掉或是HeapFree()掉这些PER_IO_CONTEXT么???  
  系统还在用这些PER_IO_CONTEXT么??它们被系统Lock   为Non   paged了么??  
   
  需要使WSASend()   WSARecv()返回再delete掉相应的内存么?  
  closesocket()能让这个SOCKET上的WSASend()   WSARecv()返回么?怎么返回,在GetQueuedCompletionStatus中返回还是怎么返回??  
   
  如果closesocket()不能让这个SOCKET上的WSASend()   WSARecv()返回,可以用  
  CancelIO(hSocket)使这个SOCKET上的WSASend()   WSARecv()返回么???  
   
   
   
   
  Top

26 楼zhujianping_es(DavidRipple)回复于 2004-11-24 20:36:39 得分 0

TCP的Keep-Alive是怎么用的?  
  我看了一下MSDN,  
  可以用setsockopt(hSock,SOL_SOCKET,SO_KEEPALIVE,,,)  
  将它启用,这个功能启用后对我们的客户突然掉线问题有没有什么帮助???Top

27 楼mynamelj(风动,帆动,仁者心动)回复于 2004-11-25 08:45:18 得分 0

反回错误信息来判断!Top

28 楼tangrh(阿唐)回复于 2004-11-25 10:26:47 得分 0

那是因为你没有投递任何重叠操作,换句话,这个连接当前是空闲的Top

29 楼baoaya(点头)(大风起兮云飞扬)回复于 2004-11-25 11:53:47 得分 0

//可以用setsockopt(hSock,SOL_SOCKET,SO_KEEPALIVE,,,)  
   
  这个会影响所有的   tcp   连接的   只适合98Top

30 楼zhujianping_es(DavidRipple)回复于 2004-11-25 18:04:40 得分 0

如果setsockopt(hSock,SOL_SOCKET,SO_KEEPALIVE,,,)  
  “这个会影响所有的   tcp   连接的”  
  那么为什么还要在这个调用中带hSock呢?  
   
  好像,Win2K下只effect   the   calling   process.  
  如果为每个socket调用setsockopt(hSock,SOL_SOCKET,SO_KEEPALIVE,,,)  
  可以在我们上面的情况下令异步Socket调用返回么?Top

31 楼zhujianping_es(DavidRipple)回复于 2004-11-25 18:13:37 得分 0

To:   tangrh(阿唐)   (   )      
        那是因为你没有投递任何重叠操作,换句话,这个连接当前是空闲的.  
  -----------------------------〉  
  不知你试过没有,我的服务端的是一直在WSARecv()的,因为我现在还没有加入任何的应用处理逻辑,  
  connect了一个client就将该客户加到Onlist   User   ListBox中去,然后就WSARecv(...)去了,  
  在客户被加到ListBox中了,我再拔线,客户仍然在ListBox中。  
   
  我在上述的三个地方(包括你说的地方)都加了错误的处理,以便到ListBox中Delete调线的客户,  
  如果客户端close   normally,客户从ListBox中删除了!  
  所以,客户异常调线,GetQueuedCompletionStatus()是不会把相应的socket上的IO调用返回的!  
   
       
     
  Top

32 楼barsteng(barsteng)回复于 2004-11-25 18:17:10 得分 0

markTop

33 楼zhujianping_es(DavidRipple)回复于 2004-11-25 18:35:58 得分 0

UPTop

34 楼vc_mfc_atl()回复于 2004-11-25 19:17:45 得分 0

心跳包什么????我用ICMP包检测客户端有没有断线,这样没问题吧Top

35 楼sixibb(四喜BB)回复于 2004-11-25 22:58:57 得分 0

来晚了:)  
  发心跳报文其实也不是必须的,在一般的网络通讯中,服务器和客户端是一样的  
  在设计的角度上,发心跳报文也就是希望服务器知道自己和客户端的连接是否发  
  生异常,但是在普通的游戏中,服务器会一直保持着和客户端的通讯。比如在同  
  服务器上的其他用户发送数据,服务器会广播给当前服务器中的所有在线用户,  
  如果没有广播这个概念,那么心跳报文那就是必须的了。  
   
  当服务器与客户端的连接发生异常时,服务器会返回一个发送失败,这时根据功  
  能的需要就要考虑是否需要重新建立连接,关闭以前的连接以回收资源了  
   
  不过大多数设计都是服务器一但发现失去连接,那么马上回收资源了,因为大多数  
  设计都是客户端发送请求重新连接的。这时,服务器就会等待客户端的重新连接。  
   
  但是有一点要注意,套结子在关闭后的240秒,系统才会释放这个SOCKET的资源,这  
  是MS说的,我现在就碰到了这个问题,导致了10055错误  
   
  如果有人有10055错误的经验请到  
  http://community.csdn.net/Expert/topic/3588/3588661.xml  
  帮一下我,无比感谢  
  或者联系我的QQ21218508Top

36 楼tangrh(阿唐)回复于 2004-11-26 08:35:28 得分 0

呵呵,有这事,我倒没有遇见,哪天试试看Top

37 楼vc_mfc_atl()回复于 2004-11-26 09:35:43 得分 0

我用ICMP包检测客户端有没有断线,这样没问题吧  
  Top

38 楼blastzgd(悟道)回复于 2004-11-26 11:07:39 得分 0

我觉得tangrh(阿唐)的办法是可行的。  
   
   
  在每次处理完数据后加RECV。  
   
  加一个RECV  
  while(1){  
  如果客户端突然断开(重启,拨网线)取完成状态的GETXXX应该会返回接收失败,此时释放资源  
  如果是正常数据接收则正常处理,处理完后再加一个RECV。  
  如果是其它:...  
  }Top

39 楼asimpleman(simple_man)回复于 2004-11-26 11:21:55 得分 0

gTop

40 楼vc_mfc_atl()回复于 2004-11-26 15:13:45 得分 0

怎么没有回答我的话的呀,晕了,  
  再说一次啦  
  我用ICMP包检测客户端有没有断线,这样没问题吧  
  Top

41 楼zhujianping_es(DavidRipple)回复于 2004-11-26 18:12:47 得分 0

有一个问题:  
  因为所有的PER_IO_CONTEXT都是通过new或是再ProcessHeap中拿来的,在  
  WSASend()   WSARecv()传递给系统之后,对方系统挂掉了,我们必须回收相关的PER_IO_CONTEXT  
  我们在closesocket()后能够直接delete掉或是HeapFree()掉这些PER_IO_CONTEXT么???  
  系统还在用这些PER_IO_CONTEXT么??它们被系统Lock   为Non   paged了么??  
   
  需要使WSASend()   WSARecv()返回再delete掉相应的内存么?  
  closesocket()能让这个SOCKET上的WSASend()   WSARecv()返回么?怎么返回,在GetQueuedCompletionStatus中返回还是怎么返回??  
   
  如果closesocket()不能让这个SOCKET上的WSASend()   WSARecv()返回,可以用  
  CancelIO(hSocket)使这个SOCKET上的WSASend()   WSARecv()返回么???Top

42 楼zhujianping_es(DavidRipple)回复于 2004-11-26 19:07:34 得分 0

UpTop

43 楼zhujianping_es(DavidRipple)回复于 2004-11-27 12:35:22 得分 0

Up  
   
  Top

44 楼hjunxu(hjun)回复于 2004-11-27 16:30:16 得分 0

vc_mfc_atl()    
  怎么没有回答我的话的呀,晕了,  
  再说一次啦  
  我用ICMP包检测客户端有没有断线,这样没问题吧  
   
  人家把ICMP禁掉了怎么检测的出来。Top

45 楼hjunxu(hjun)回复于 2004-11-27 16:40:56 得分 0

感觉还是楼主的需求有点特别,一般服务器才不会去关客户机的死活呢,那不是太累了。Top

46 楼pclili(黑客天使)回复于 2004-11-27 20:16:00 得分 0

if(bRet   ==   false   &&   &(lpOverlappedData->Overlapped)   ==   NULL)  
  {//接收出错  
  cout   <<   "GetQueuedCompletionStatus   error.   Error   code:   "   <<   GetLastError()   <<   endl;  
  return   1;  
  }  
  else   if(bRet   ==   false   &&   &(lpOverlappedData->Overlapped)   !=   NULL)  
  {  
  cout   <<   (unsigned   int)lpCompletionKey->socket   <<   "   非法退出"   <<   endl;  
   
  if(closesocket(lpCompletionKey->socket)   ==   SOCKET_ERROR)  
  {  
  cout   <<   "关闭套接字失败"   <<   endl;  
  }  
   
  GlobalFree(lpOverlappedData);  
  GlobalFree(lpCompletionKey);  
  }  
  else   if(dwNumOfBytes   ==   0)  
  {  
  cout   <<   (unsigned   int)lpCompletionKey->socket   <<   "   已关闭端口"   <<   endl;  
   
  if(closesocket(lpCompletionKey->socket)   ==   SOCKET_ERROR)  
  {  
  cout   <<   "关闭套接字失败"   <<   endl;  
  }  
   
  GlobalFree(lpOverlappedData);  
  GlobalFree(lpCompletionKey);  
   
  continue;  
  }  
  else  
  {  
  //收发数据  
                                        }Top

47 楼pclili(黑客天使)回复于 2004-11-27 20:16:56 得分 0

BOOL bRet   =   0;  
  LPOVERLAPPED lpOverlapped   =   NULL;  
  LPCompletionKey lpCompletionKey     =   NULL;  
  LPOverlappedData lpOverlappedData   =   NULL;  
  DWORD dwNumOfBytes   =   0;  
  DWORD dwRecvBytes   =   0;  
  DWORD dwSendBytes   =   0;  
  DWORD dwFlags   =   0;Top

48 楼pclili(黑客天使)回复于 2004-11-27 20:18:47 得分 0

LPCompletionKey,   LPOverlappedData为自定义结构!  
  我试过了,如果client直接关掉程序,就是非法退出,如果执行了closesocket(..),就是已关闭端口,即正常退出。Top

49 楼nonocast(如果没有如果)回复于 2004-11-28 00:31:33 得分 0

要拔网线试  
  服务端不会有任何反应的  
  TCP之所以不用保活就是因为效率太低  
  但你又要维持连接关系  
  一定用心跳  
  只不过多开一个线程  
  非常容易Top

50 楼zhujianping_es(DavidRipple)回复于 2004-11-28 17:59:54 得分 0

是,用心跳。  
  可是,没有返回得WSARecv,WSASend()   调用所占用得资源怎么释放掉!  
  它们还没返回,  
  可以直接closesocket(hSock)把它们干掉。  
  然后,delete掉PER_IO_CONTEXT的Buffer么  
  Top

51 楼PiggyXP(【小猪】技术太差没脸上班,只好去念Ph.D了-_-b)回复于 2004-11-28 21:56:50 得分 0

To   黑客天使:  
             
                如果客户端拔掉网线呢?  
   
  To   vc_mfc_atl()   :  
       
                很多防火墙的默认设置就是禁掉icmp,而且发送icmp数据包要比发送心跳包要麻烦的多  
   
          其实心跳包是个挺理想的方案,不少大型的网络应用也都是采用的心跳包的机制来确认客户端的连接Top

52 楼zhujianping_es(DavidRipple)回复于 2004-11-29 20:59:52 得分 0

Who   can   answer   my   question?Top

53 楼redchina(风清云淡)回复于 2004-11-30 13:33:37 得分 0

在新开的心跳包检测线程里边难道不可以释放该资源?如果你觉得它不能释放,能说出理由么?心跳包检测线程作为一个独立的线程,WSARecv,WSASend()一般都是异步调用,直接返回的,你可以用你的检测线程来修改你的资源,应该是可以成功的,你不相信试试看~~~~Top

54 楼redchina(风清云淡)回复于 2004-12-01 09:33:25 得分 0

quote:zhujianping_es(DavidRipple)    
   
  需要使WSASend()   WSARecv()返回再delete掉相应的内存么?  
  closesocket()能让这个SOCKET上的WSASend()   WSARecv()返回么?怎么返回,在GetQueuedCompletionStatus中返回还是怎么返回??  
  ----------------------------------------------------------------------  
  If   a   socket   handle   associated   with   a   completion   port   is   closed,   GetQueuedCompletionStatus   returns   ERROR_SUCCESS,   with   *lpOverlapped   non-NULL   and   lpNumberOfBytes   equal   zero.Top

55 楼hellowithsmile(张三^_^江南小百姓+抵制日货)回复于 2004-12-01 10:32:03 得分 0

偶也遇到同样的问题:发送心跳包就行了。  
  具体用client发送一个5个bytes简单命令,  
  server收到后直接回发,这样造成c/s之间一直存在数据收发,  
  客户端一旦在一定时间内说不到服务器数据,就认为服务器断掉。  
  服务器每次遍历socket时,检查返回值就行了。Top

56 楼baoaya(点头)(大风起兮云飞扬)回复于 2004-12-01 10:47:32 得分 0

使用SIO_KEEPALIVE_VALS关键字   调用     WSAIoctl   试试  
   
  tcp_keepalive   keepAlive   =   {   TRUE,   10000,   1000   };  
  DWORD   tmp;  
  WSAIoctl(   obj->m_sock,   SIO_KEEPALIVE_VALS,    
  &keepAlive,   sizeof(   keepAlive   ),   0,   0,   &tmp,   NULL,   NULL   );  
   
  Top

57 楼zhujianping_es(DavidRipple)回复于 2004-12-01 20:19:02 得分 0

To   baoaya(点头)   (   ):  
        If   use   the   tcp   keep-alive   mechanism,will   the   TCP-Application   get   the   keep-alive   packet?   or   it   is   done   by   TCP/IP   stack   for   you   ??  
   
  To   redchina(风清云淡):  
          Have   you   ever   tried   this   case??   Now   I   can't   test   this   on   my   server.   If   the   things   go  
  like   what   you   said,then   what   I   do   will   be   a   mess,I   do   like   this:  
  Pesudo-flowchart:  
      If(don't   get   heartbeat   packet   for   consecutive   3   times)  
  {  
              CancelIo(pUser->m_pPerHandleContext->hSocket);  
              closesocket(pUser->m_pPerHandleContext->hSocket);  
            //Delete   the   WSASend()   related   PerIoContext    
            for(pos=m_lstIoContextListOnThisSocket.GetHeadPosition();pos!=NULL;)  
            {  
                                  pPerIoContext=m_lstIoContextListOnThisSocket.GetNext(pos);  
                                  delete   pPerIoContext;  
            }  
            //delete   the   WSARecv()   related   PerIoContext  
            delete   pPerIoContextRecv;  
   
          //free   the   PerHandleContext  
          delete   pUser->m_pPerHandleContext;  
  }  
   
  -------------------------->  
  I   don't   know   if   the   pesudo-code   like   above   will   work,but   I   will   try   .However,it   would   be  
  some   weeks   later   after   I   complete   the   Work   logic   mess!!!    
  Any   one   who   get   such   experience   ,please   give   a   hand.Thank   U!!!!!!!!  
  Top

58 楼redchina(风清云淡)回复于 2004-12-02 18:41:18 得分 0

 
  quote:  
  回复人:   zhujianping_es(DavidRipple)   (   )   信誉:106     2004-11-26   18:12:47     得分:   0      
     
  有一个问题:  
  因为所有的PER_IO_CONTEXT都是通过new或是再ProcessHeap中拿来的,在  
  WSASend()   WSARecv()传递给系统之后,对方系统挂掉了,我们必须回收相关的PER_IO_CONTEXT  
  我们在closesocket()后能够直接delete掉或是HeapFree()掉这些PER_IO_CONTEXT么???  
  系统还在用这些PER_IO_CONTEXT么??它们被系统Lock   为Non   paged了么??  
  ----------------------------------------------------------------------------------------  
   
   
  你所担心的应该是这些资源被锁定,所以,   你觉得你不应该直接删除这些资源?  
   
  就算你把AFD.SYS的缓冲关闭,系统所作的就是当应用程序收发数据时,将应用程序缓冲区的所有页面将被锁定到物理内存中,如果你没有关闭AFD.SYS的缓冲,系统一般只是将进程的工作组(working   set页锁定在物理内存中。锁定内存的含义是让其页面驻留在物理内存中,不允许在将其映射到磁盘上的同时将其映射出内存。但是它并不禁止你修改该内存的权力。  
  Top

59 楼hxzb7215191(天行健,君子以自强不息)回复于 2004-12-02 19:50:31 得分 0

MARK    
  upTop

60 楼zhujianping_es(DavidRipple)回复于 2004-12-03 18:09:42 得分 0

redchina(风清云淡)   (   )   :  
        我现在的问题是我现在释放那些资源,但那些资源的使用者WSARecv()   WSASend()都没有返回,  
  我就这样“暴力”的删除,系统会complain么??  
        本进程中被内核afd.sys锁定的内存,我可以就这么释放么?Top

61 楼pclili(黑客天使)回复于 2004-12-04 01:56:38 得分 0

拔掉网线会是什么样子,还真没试过,明天来试试。  
  知道了告诉你结果:)  
   
  ^_^   PiggyXP(【小猪】●至爱VC,至爱网络版●)   ^_^   我下次发个好贴了,帮我至预^_^Top

62 楼pclili(黑客天使)回复于 2004-12-04 01:57:03 得分 0

今天写了一天,过几天发出来Top

63 楼zhujianping_es(DavidRipple)回复于 2004-12-04 18:17:26 得分 0

呵呵,Waiting!!!!  
  谁有用GetQueuedCompletionStatus()做的基于完成端口的demo(要有用户掉线检测机制)的  
  程序,可否发上来看看,400分相送!Top

64 楼redchina(风清云淡)回复于 2004-12-05 15:17:49 得分 0

quote:  
  回复人:   zhujianping_es(DavidRipple)   (   )   信誉:106    
        我现在的问题是我现在释放那些资源,但那些资源的使用者WSARecv()   WSASend()都没有返回,  
  我就这样“暴力”的删除,系统会complain么??  
        本进程中被内核afd.sys锁定的内存,我可以就这么释放么?  
  -------------------------------------------------------------------------------------  
  如果你害怕这样的问题出现你无法预料的后果,使用S   E   H至少可以保证你的程序不会崩溃,顶多是你的程序不会发送(或者接受)成功,何况这个不发送的操作也是你需要的.  
  Top

65 楼redchina(风清云淡)回复于 2004-12-05 15:18:43 得分 0

quote:  
  回复人:   zhujianping_es(DavidRipple)   (   )   信誉:106    
        我现在的问题是我现在释放那些资源,但那些资源的使用者WSARecv()   WSASend()都没有返回,  
  我就这样“暴力”的删除,系统会complain么??  
        本进程中被内核afd.sys锁定的内存,我可以就这么释放么?  
  -------------------------------------------------------------------------------------  
  如果你害怕这样的问题出现你无法预料的后果,使用S   E   H至少可以保证你的程序不会崩溃,顶多是你的程序不会发送(或者接受)成功,何况这个不发送的操作也是你需要的.  
  Top

66 楼zhujianping_es(DavidRipple)回复于 2004-12-05 18:02:33 得分 0

Up  
  Top

67 楼sohou(2007的春天)回复于 2004-12-05 23:31:00 得分 0

我现在的问题是我现在释放那些资源,但那些资源的使用者WSARecv()   WSASend()都没有返回,  
  我就这样“暴力”的删除,系统会complain么??  
        本进程中被内核afd.sys锁定的内存,我可以就这么释放么?  
  =========  
  没问题的,可以的,听我的!  
  检测到有错误后,关闭SOCKET,在释放perhandle   和perio  
  Top

68 楼luoxiangdong(敏捷软件开发团队)回复于 2004-12-06 08:39:11 得分 0

其实很简单,服务器的WSARecv会收到一个0长度的包,这时就可以认为客户端网络断线或者正常断开Top

69 楼zhujianping_es(DavidRipple)回复于 2004-12-06 18:01:07 得分 0

sohou(大秦之刃(水平太菜,埋头灌水好了))   (   )    
  quto:  
  没问题的,可以的,听我的!  
  :)Top

70 楼zhujianping_es(DavidRipple)回复于 2004-12-09 18:10:35 得分 0

UpTop

71 楼baoaya(点头)(大风起兮云飞扬)回复于 2004-12-10 09:24:16 得分 0

小弟以为心跳包是必须的,因为   如果互相经常不发数据,那些建立连接的网关为了节省资源会把连接断掉的Top

72 楼baodi_z(冷冷的太阳)回复于 2004-12-10 10:35:52 得分 0

反正比较常用的方法就是:  
  heartbeat包   +   timeout来判定连接是否活动  
   
  我是进来学习更好的方法的  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值