我用心跳去检测客户端.这个时候把客户端那台机的网线拨掉.我的心跳WSASend返回值一样是"永远"成功.GetQueuedCompletionStatus也永远都是成功的.我查了一些资料,听了网友们的建议,说是投递一个读操作.OK,我在发心跳包后又投递了一个WSARecv.GetQueuedCompletionStatus永远都没有读的反应.这个时候,我把客户机的网线插上,GetQueuedCompletionStatus就猛烈的跳出读操作..我汗...完全没办法判断.求助.

解决方案 »

  1.   

    OK,我在发心跳包后又投递了一个WSARecv.GetQueuedCompletionStatus永远都没有读的反应.这个时候,我把客户机的网线插上,GetQueuedCompletionStatus就猛烈的跳出读操作..*****************************************************************是因为 tcp 监测是否连接断开也是靠发送数据和发送回应来检测的,你上面说到的现象个人认为是由于tcp的默认连接检测时间间隔造成的,如果你等足够长的时间,WSARecv应该是可以返回失败的。
      

  2.   

    另外一种作法:记得有一个函数是可以检测到本机的网络是否断开(包括拔掉网线),此时,如果客户端监测断开时 shutdown 然后 closesocket, 估计网线在插上时服务器就不会出现你说的现象了。
      

  3.   

    如楼上所说,可以用一问一答的方式.我现在的疑问就是说,为什么断开这后,GetQueuedCompletionStatus还是告诉我发送成功呢?还有大问题,就是,我判断到断线之后,我怎么样去释放那些new出来的空间啊?
    比如perHandle和perIO,这两个东西都是GetQueuedCompletionStatus填充给我,我才能删的啊.这个时候我尝试了把这些地址都保存到结构里面,OK,可以删除了.但是一删除后,GetQueuedCompletionStatus马上就有反应了.这个时候向下执行,perHandle和perIO就都是空地址了,就报错了.这个是大问题,怎么释放空间???????
      

  4.   

    我现在的疑问就是说,为什么断开这后,GetQueuedCompletionStatus还是告诉我发送成功呢?************************************************************************个人理解: 应该是因为 GetQueuedCompletionStatus 返回成功只是意味着你要发送的数据被成功的放置到系统的发送缓冲区而已吧!,他不代表数据已经发送到对方的接收缓冲区中了。
    还有大问题,就是,我判断到断线之后,我怎么样去释放那些new出来的空间啊?
    比如perHandle和perIO,这两个东西都是GetQueuedCompletionStatus填充给我,我才能删的啊.这个时候我尝试了把这些地址都保存到结构里面,OK,可以删除了.但是一删除后,GetQueuedCompletionStatus马上就有反应了.这个时候向下执行,perHandle和perIO就都是空地址了,就报错了.这个是大问题,怎么释放空间???????********************************************************************个人观点,未经测试,仅供参考:)你检测到网线断开后就应该显示的关闭套接字啊,关闭后GetQueuedCompletionStatus应该就能返回你原来投递的数据了,这时你可以释放资源。
      

  5.   

    我现在用的方式是这样.服务器计时.客户端定时如1分钟向服务器发个数据,服务器对这个客户的计时就刷新.如果长时间客户端没发来数据.服务器查出这个客户socket,就close了(就算它掉线了).
      

  6.   

    to ProgrameMan(我要学汇编):
    你检测到网线断开后就应该显示的关闭套接字啊,关闭后GetQueuedCompletionStatus应该就能返回你原来投递的数据了,这时你可以释放资源。
    -------------------------------------------------
    谢谢,我试过了,关闭SOCKET后,GetQueuedCompletionStatus无任务响应.....
      

  7.   

    to ProgrameMan(我要学汇编):
    你检测到网线断开后就应该显示的关闭套接字啊,关闭后GetQueuedCompletionStatus应该就能返回你原来投递的数据了,这时你可以释放资源。
    -------------------------------------------------
    谢谢,我试过了,关闭SOCKET后,GetQueuedCompletionStatus无任务响应.....********************************************************************你要释放的资源是哪端的啊!服务器还是客户端?
      

  8.   

    TCP/IP协议只封装软件错误,不管硬件错误.所以你直接拔掉网线或者剪断网线,TCP/IP协议是不管的,仍认为传输正常.正确做法是在服务器端没隔多少秒就检查一遍,发一个确认帧去检查.基本上都是这么实现的.
      

  9.   

    最简单用so_keepalive, 默认2小时才检测一次。。定时自发心跳包,超时没收到回应,客户端就是断开了。
      

  10.   

    没理解透TCP/IP层的实现才会出现这个问题
    这和采用什么模型根本没有关系,由于TCP协议本身的问题
    必须由你自己的协议检测连接是否依然正常,也就是必须由你自己的协议来保证不要去使用心跳包,使用那个东西,你做出来的服务器只能是理论上的
    应该用你自己的协议来保证网络的检测
      

  11.   

    没理解透TCP/IP层的实现才会出现这个问题
    这和采用什么模型根本没有关系,由于TCP协议本身的问题
    必须由你自己的协议检测连接是否依然正常,也就是必须由你自己的协议来保证这个东西不能这么说,  对方异常断线, 服务器需要2msl 才能真正知道。 75s很长啊。
    所以大家主要想知道一个快速判断的办法 so_keepalive 并不通用。steven 说看实现。不要去使用心跳包,使用那个东西,你做出来的服务器只能是理论上的
    应该用你自己的协议来保证网络的检测msn 的做法 就是靠逻辑层心跳 30s 内必须有"PNG 命令" 进行逻辑判断。纯粹的判断数据是否到达客户端并无太大意义,steven 举过很多例子, 数据到来对方的tcp 栈 但是没有到逻辑层系统就崩溃了。 所以用心跳才更加有意义。但我目前想知道的是 如何定时,和如何删掉端口。
      

  12.   

    我所说的定时器不是一般意义上定时器。
    你能给分吗,给分我就回答你的问题,呵呵,开玩笑了1. struct time_node{
           long id;   // 用户ID
           unsigned long timeout;
       }
    2. 服务器接收到一个用户的心跳包时,从时间链表中删除自己的时间节点,然后计算并更新新的超时值,然后放到时间链表的尾部(也就是说时间小的一定在链表的前端)
    3. 开辟一个线程,该线程每隔1秒钟检测一次时间链表
    4. 检测线程从链表中区出元素和当前时间比较,如果比当前时间小则说明该用户已经超时了然后继续取下一个元素,直到找到比当前时间大的元素然后 Sleep 1秒
    上面是大致的过程,写得比较乱,对付看吧 呵呵
      

  13.   

    就是我所说的 一个队列不停循环队列按照需要等待时间的长度存放。我就是这个意思。 我考虑的是插入线程需要和循环线程互斥才可以。 当用户很多的时候,需要对整个队列的n(n-1)/2 进行比较,效率是不是会很低? 而且当有其他问题出现,需要删除某个端口的时候,又需要在这个队列遍历一次,去除所有long id;   // 用户ID 相关的定时器。 那么可能就有3个线程相互交错了。 如果还有其他情况加入,是否会越来越复杂而难以驾御?
      

  14.   

    我考虑的是插入线程需要和循环线程互斥才可以。 当用户很多的时候,需要对整个队列的n(n-1)/2 进行比较,效率是不是会很低? 而且当有其他问题出现,需要删除某个端口的时候,又需要在这个队列遍历一次,去除所有long id;   // 用户ID 相关的定时器。 那么可能就有3个线程相互交错了。 如果还有其他情况加入,是否会越来越复杂而难以驾御——————————————你说的是常规的算法啊,可以实现的很高效的
      

  15.   

    需要对整个队列的n(n-1)/2 进行比较,效率是不是会很低?
    而且当有其他问题出现,需要删除某个端口的时候,又需要在这个队列遍历一次,去除所有long id;
    *******************************************************为什么要这么做呢? 其实可以很简单啊
      

  16.   

    to benjiam(今晚打老虎) 我先回家了,晚上在讨论,其实你把问题局部化了,你把思路放大一些就会发现其实不用像你说的那样做。
      

  17.   

    恩,TCP/IP是不能保证立刻检测到服务器断开的,可以用GetIfEntry检测网卡的状态,CS程序通常由客户发心跳,服务器定时检测的方法来做,检查的时间可以更加程序自身的需要来设置
      

  18.   

    C#虽然历史很短,但专门为.Net度身定做,不向VB.Net那样要背负历史包袱
      

  19.   

    需要对整个队列的n(n-1)/2 进行比较,效率是不是会很低?
    指的平均值而且当有其他问题出现,需要删除某个端口的时候,又需要在这个队列遍历一次,去除所有long id;当一个端口被删除,需要删除掉所有相关的定时器吧。 不然到时候定时器到了,取到的数据就已经失效了。被删除了
      

  20.   

    如果我实现一个双向链表,结构如下class list_node
    {
    public:
          list_node *next;
          list_node *prev;
    }
    在为每个连接(客户端)建立一个类class client
    {
     public:
          long id;
          int  sock;
          unsigned long time_out;
          list_node node;
    }
    你说我在删除的时候容易不?
      

  21.   

    to benjiam(今晚打老虎) 咱俩跑题了吧 呵呵
      

  22.   

    是这个吗?http://community.csdn.net/Expert/TopicView3.asp?id=5209711
      

  23.   

    :benjiam(今晚打老虎)

    是这个吗?http://community.csdn.net/Expert/TopicView3.asp?id=5209711多次投递,没找到阿,贴个连接出来
      

  24.   

    http://community.csdn.net/Expert/topic/5213/5213726.xml?temp=.4187128一不小心贴错版了
      

  25.   

    http://community.csdn.net/Expert/TopicView1.asp?id=5213726