分享

服务器如何在SOCKET通讯中知道客户端断开连接或掉线了???[

 haodafeng_org 2011-03-24
发表于:2002-06-14 09:52:34
我用Socket做了一个服务器和客户端,服务器在客户端连接时能知道,但客户端断开或掉线服务器就不知道了,请问大虾们有好办法吗?
  • pfans用户头像
  • pfans
  • (pfans)
  • 等 级:
#1楼 得分:0回复于:2002-06-14 13:30:11
有人知道吗?
#2楼 得分:0回复于:2002-06-14 13:59:37
帮你抬
#3楼 得分:0回复于:2002-06-14 14:07:05
如果Client端断开连接,在Server端Recv时会返回0
但如果Client端掉线就不行了,你可以通过定时检查某个连接是否有数据发送
来确定,如果长时间无数据发送就认为已掉线
#4楼 得分:0回复于:2002-06-14 14:11:16
判断OnClose函数,定时ping一次都可以
http://www.csdn.net/expert/topic/563/563231.xml?temp=.297085
#5楼 得分:0回复于:2002-06-14 14:26:25
用select啊。
  • pfans用户头像
  • pfans
  • (pfans)
  • 等 级:
#6楼 得分:0回复于:2002-06-22 08:59:45
我没有用CSocket类,用的是SDK.
#7楼 得分:0回复于:2002-06-22 21:02:45
How   do   I   detect   when   my   TCP   connection   is   closed?
All   of   the   I/O   strategies   discussed   in   the   I/O   strategies   article   have   some   way   of   indicating   that   the   connection   is   closed.

First,   keep   in   mind   that   TCP   is   a   full-duplex   network   protocol.   That   means   that   you   can   close   the   connection   half-way   and   still   send   data   on   the   other   half.   An   example   is   a   web   browser:   it   sends   a   short   request   to   the   web   server,   then   closes   its   half   of   the   connection.   The   web   server   then   sends   back   the   requested   data   on   the   other   half   of   the   connection,   and   closes   its   sending   side,   which   terminates   the   TCP   session.

Normal   TCP   programs   only   close   the   sending   half,   which   the   remote   peer   perceives   as   the   receiving   half.   So,   what   you   normally   want   to   detect   is   whether   the   remote   peer   closed   its   sending   half,   meaning   you   won 't   be   receiving   data   from   them   any   more.

With   asynchronous   sockets,   Winsock   sends   you   an   FD_CLOSE   message   when   the   connection   drops.   Event   objects   are   similar:   the   system   signals   the   event   object   with   an   FD_CLOSE   notification.

With   blocking   and   non-blocking   sockets,   you   probably   have   a   loop   that   calls   recv()   on   that   socket.   recv()   returns   0   when   the   remote   peer   closes   the   connection.   As   you   would   expect,   if   you   are   using   select(),   the   SOCKET   descriptor   in   the   read_fds   parameter   gets   set   when   the   connection   drops.   As   normal,   you 'll   call   recv()   and   see   the   0   return   value.

As   you   might   have   guessed   from   the   discussion   above,   it   is   also   possible   to   close   the   receiving   half   of   the   connection.   If   the   remote   peer   then   tries   to   send   you   data,   the   stack   will   drop   that   data   on   the   floor   and   send   a   TCP   RST   to   the   remote   peer.

#8楼 得分:0回复于:2002-06-22 21:03:12
How   do   I   detect   an   abnormal   network   disconnect?
The   previous   question   deals   with   detecting   when   a   protocol   connection   is   dropped   normally,   but   what   if   you   want   to   detect   other   problems,   like   unplugged   network   cables   or   crashed   workstations?   In   these   cases,   the   failure   prevents   notifying   the   remote   peer   that   something   is   wrong.   My   feeling   is   that   this   is   usually   a   feature,   because   the   broken   component   might   get   fixed   before   anyone   notices,   so   why   force   everyone   to   restart?

If   you   have   a   situation   where   you   must   be   able   to   detect   all   network   failures,   you   have   two   options:

The   first   option   is   to   give   the   protocol   a   command/response   structure:   one   host   sends   a   command   and   expects   a   prompt   response   from   the   other   host   when   the   command   is   received   or   acted   upon.   If   the   response   does   not   arrive,   the   connection   is   assumed   to   be   dead,   or   at   least   faulty.

The   second   option   is   to   add   an   "echo "   function   to   your   protocol,   where   one   host   (usually   the   client)   is   expected   to   periodically   send   out   an   "are   you   still   there? "   packet   to   the   other   host,   which   it   must   promptly   acknowledge.   If   the   echo-sending   host   doesn 't   receive   its   response   or   the   receiving   host   fails   to   see   an   echo   request   for   a   certain   period   of   time,   the   program   can   assume   that   the   connection   is   bad   or   the   remote   host   has   gone   down.

If   you   choose   the   "echo "   alternative,   avoid   the   temptation   to   use   the   ICMP   "ping "   facility   for   this.   If   you   did   it   this   way,   you   would   have   to   send   pings   from   both   sides,   because   Microsoft   stacks   won 't   let   you   see   the   other   side 's   echo   requests,   only   responses   to   your   own   echo   requests.   Another   problem   with   ping   is   that   it 's   outside   your   protocol,   so   it   won 't   detect   a   failed   TCP   connection   if   the   hardware   connection   remains   viable.   A   final   problem   with   the   ping   technique   is   that   ICMP   is   an   unreliable   protocol:   does   it   make   a   whole   lot   of   sense   to   use   an   unreliable   protocol   to   add   an   assurance   of   reliability   to   another   protocol?

Another   option   you   should   not   bother   with   is   the   TCP   keepalive   mechanism.   This   is   a   way   to   tell   the   stack   to   send   a   packet   out   over   the   connection   at   specific   intervals   whether   there 's   real   data   to   send   or   not.   If   the   remote   host   is   up,   it   will   send   back   a   similar   reply   packet.   If   the   TCP   connection   is   no   longer   valid   (e.g.   the   remote   host   has   rebooted   since   the   last   keepalive),   the   remote   host   will   send   back   a   reset   packet,   killing   the   local   host 's   connection.   If   the   remote   host   is   down,   the   local   host 's   TCP   stack   will   time   out   waiting   for   the   reply   and   kill   the   connection.

There   are   two   problems   with   keepalives:

Only   Windows   2000   allows   you   to   change   the   keepalive   time   on   a   per-process   basis.   On   older   versions   of   Windows,   changing   the   keepalive   time   changes   it   for   all   applications   on   the   machine   that   use   keepalives.   (Changing   the   keepalive   time   is   almost   a   necessity   since   the   default   is   2   hours.)  

Each   keepalive   packet   is   40   bytes   of   more-or-less   useless   data,   and   there 's   one   sent   each   direction   as   long   as   the   connection   remains   valid.   Contrast   this   with   a   command/response   type   of   protocol,   where   there   is   effectively   no   useless   data:   all   packets   are   meaningful.   In   fairness,   however,   TCP   keepalives   are   less   wasteful   on   Windows   2000   than   the   "are   you   still   there "   strategy   above.  

Note   that   different   types   of   networks   handle   physical   disconnection   differently.   Ethernet,   for   example,   establishes   no   link-level   connection,   so   if   you   unplug   the   network   cable,   a   remote   host   can 't   tell   that   its   peer   is   physically   unable   to   communicate.   By   contrast,   a   dropped   PPP   link   causes   a   detectable   failure   at   the   link   layer,   which   propagates   up   to   the   Winsock   layer   for   your   program   to   detect.

#9楼 得分:0回复于:2002-06-22 21:04:33
select   FD_CLOSE|FD_READ|...
  • anjy用户头像
  • anjy
  • (泡泡oοО○)
  • 等 级:
#10楼 得分:0回复于:2002-06-22 21:05:48
Onclose()
#11楼 得分:0回复于:2002-06-22 21:24:58
设置超时设置或者单独开1个线程检查各个线程是否ACTIVE,是否超时,
如果超时的话就根据你的系统KILL掉或者挂起。
这里应该设置有同步变量来控制。
#12楼 得分:0回复于:2002-06-22 21:52:36
你是用的sdk,

你使用WSAAsyncSelect()函数,自定义消息WM_SOCKET,然后铺捉FD_ACCEPT等等,在处理消息的开始的时候先判断是否出现网络错误
如下:

case     WM_SOCKET:
if(WSAGETSELECTERROR(lParam))
{
        if(WSAGETSELECTERROR(lParam)   ==   WSAECONNABORTED)
      {
          //   如果客户端关闭socket,就产生这个错误
        }
        else
        {
          //   其他socket错误
        }
}

OK?
  • limin用户头像
  • limin
  • (不留名)
  • 等 级:
#13楼 得分:0回复于:2002-06-22 22:17:29
我认为应该设置单独的检查在线机制,关于   FD_CLOSE   或者   OnClose   仅仅只能判断socket的正常的close   ,对于非正常的吊线是无法检测的。
#14楼 得分:0回复于:2002-07-08 15:43:29
select   FD_CLOSE|FD_READ|FD_CLOSE
  • mfkzj用户头像
  • mfkzj
  • (鹰翔)
  • 等 级:
#15楼 得分:0回复于:2002-07-08 16:44:49
你使用WSAAsyncSelect()函数,自定义消息WM_SOCKET,然后铺捉FD_ACCEPT等等,在处理消息的开始的时候先判断是否出现网络
可以设置中断时间   如果在相隔时间内客户端没有进行任何操作   就可以设定对方超时   中断连接
#16楼 得分:0回复于:2002-07-08 17:03:20
TCP/IP在设计时,并没有考虑到侦测网络连线断开这种情形,因为设计目标是适应恶劣的环境的,应用程序必须自己检测这种错误情况。一般是在recv函数检查有没有错误,具体情况可参照一些书籍的详细介绍。
      推荐的方法就是如前面所说使用在线检查机制,定时传送数据报,确认对方是否还在线。路由器和路由器之间的检测就是这种形式
  • hzyem用户头像
  • hzyem
  • (大峡)
  • 等 级:
#17楼 得分:0回复于:2002-07-08 17:21:59
使用定时器定时向客户端发送数据包,接收方收到后返回应答数据包,如果超过一定时间没有应答就可以认为连接已断开。
#18楼 得分:0回复于:2002-07-08 17:27:35
不知道用GetlastEorror()可不可以?反正我每交断了GetlastEorror就为10054
#19楼 得分:0回复于:2002-07-08 17:34:34
gz
#20楼 得分:0回复于:2002-07-08 19:31:01
帮你UP!
#21楼 得分:0回复于:2002-07-10 01:58:48
自己实现检测机制。tcp/ip不提供这种功能
#22楼 得分:0回复于:2002-07-10 01:59:09
winsock也没有
  • jfzsl用户头像
  • jfzsl
  • (剿匪总司令)
  • 等 级:
#23楼 得分:0回复于:2002-07-12 12:56:12
up
  • sans用户头像
  • sans
  • (长风半日)
  • 等 级:
  • 2

#24楼 得分:0回复于:2002-07-12 13:22:59
我原来一直也在为这个问题烦恼,最近解决了,方法如下:
在Server端使用Select进行检查,同时设定TimeOut,如10分钟;
在Client端开一个线程,定一个时间,如1分钟就向Server发送一个信号,当Server端如果10分钟还收不到Client端发来的信号,就关闭该Client的服务。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多