具体编程是这样的,用VC++6.0编写了客户端和服务器端的Dll,两边都是阻塞模式,因为数据十分重要,客户端保留数据备份。
两边都用一个类继承了CSocket类,重载了几个事件 Onclose  OnReceive OnAccept等。
在网络正常的情况下,客户端和服务器连接和断开都可以正常检测的到,也没有什么问题。
在我拔下服务器端的网线,客户端用 dwRealSendDataLength = m_pSocket.send(ucSendBuff,4) 检测网络状态,当dwRealSendDataLength != 4  时认为网络被物理中断,尝试重新连接。
当网络在远端断开(Client端检测,Server端断开,用HUB连接)此时很难用上述方法检测到断开了(Client端用定时检测的方法,返回状态标志),而在Client端本机网线拔下的时候比较容易检测得到。在我检测到没有断开而实际已经被拔掉网线的时候,我发送数据(30K左右)就会被阻塞,搞的我很痛苦,恳请各位高手指导。我的问题是:Client端在已经和远端已知IP和Port服务器建立连接的情况下,定时检测的时候,如何有效检测这个连接已经断开,或者是检测和那台机子的连接出现了物理断开(相当于网线拔掉或网络故障),请各位高手不吝赐教,感激不尽。

解决方案 »

  1.   

    也许你发的数据量太少了,如果多发一点会独发OnClose
      

  2.   

    双方(客户端和服务器)都要加断开的判断才可以.
    你服务器端利用与客户连接的Socket对象定时检测的方法.
      

  3.   

    在用VC++写测试的时候,也就是没有做成DLL时,两边都检测的,
    但是效果是一样的,只要是自己这头的网线拔掉,不久就可以检测到,
    但是局域网另一端网线被拔掉的时候,就很难检测的到了,就是我说的,除非我发实际的数据
    (30K左右 有图片数据和文本数据)会被阻塞,翘了,一直到网络好了,程序才会正常连接上,而用测试数据4个字节,发几十次是检测不到的。
    而我不希望那样,因为在检测到网络断开的时候,我要求客户段重新尝试连接,而不要阻塞。
    在这个时候,客户端还有十分重要的事情需要处理,包括数据加入数据库,数据图像显示,模式识别,等,虽然有些处于不同的线程,但会把主线程阻塞的。
      

  4.   

    而用测试数据4个字节,发几十次是检测不到的。
    ----------------------------------------------
    TCP/IP协议规定了一个数据包的最大长度(MSS)。如果客户连续发送大量的小数据,则将这些数据拼成一个往往比分割成多个小包要好,因为数据包的封装需要一定开销。Nagle的原理主要就是在缓冲区中的数据少于MSS的时候(可能是上一次发包时留下的尾巴,也可能是应用程序就发了这么点数据),内核会等到上一个数据包被对方确认了之后,才能发出(主要是希望这段时间里应用程序能多发一些数据,凑成一个大包一起发出)。而不要阻塞
    -------------------
    int TimeOut=1000; //设置发送超时1秒
    if(::setsockopt(cClient,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
    return 0;
    }
      

  5.   

    当然这个优化也可以关掉,通过setsockopt关掉neagle算法.
    -----
    MSDN:
    SetSockOpt( int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel = SOL_SOCKET );
    The TCP_NODELAY option disables the Nagle algorithm. The Nagle algorithm is used to reduce the number of small packets sent by a host by buffering unacknowledged send data until a full-size packet can be sent. However, for some applications this algorithm can impede performance, and TCP_NODELAY can be used to turn it off. Application writers should not set TCP_NODELAY unless the impact of doing so is well-understood and desired, since setting TCP_NODELAY can have a significant negative impact on network performance. TCP_NODELAY is the only supported socket option which uses level IPPROTO_TCP; all other options use level SOL_SOCKET.
      

  6.   

    不是很明白,是不是整个通讯都是用API写的啊,
    我继承CSocket类写的,可不可以用啊?
      

  7.   

    也就是说,因为默认用Nagle优化,你send的pack小于MSS(1460Bytes),他是不会send出去的,
    这就是你为什么send 4Bytes几十次都收不到的原因。understand?
    你可以去掉Nagle优化。(方法看前几个帖)
    至于你说的阻塞问题可以用以下方法减少阻塞的时间:
    int TimeOut=1000; //设置发送超时1秒
    if(::setsockopt(cClient,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){
    return 0;
    }
      

  8.   

    Sander兄,真是不好意思,有点不明白,再问一下。
    当我平时没有拔掉网线的时候,都是挺好的,2个数据都可以正常发送啊,并没有等待。我是为了在任何情况下都可以自动恢复连接,不要等待很长时间,不会引起主线程停止才需要检测。现在我是这样做的,发送之前检测一下网络是否被阻塞了,如果被阻塞了,取消阻塞,
    尝试重新连接。(客户端)不过这样很慢,虽然可以检测得到。就是在网络断开的情况下,不知道有没有方法可以比较快的检测到,例如(服务器端非正常关机,服务器端网线被拔掉),我是否可以在客户端较快的检测到这个连接断开了,而可以启动定时的尝试连接。
      

  9.   

    我也遇到这种情况,我见很多人都是设置发送和接收超时,(不让程序阻塞)再就是在程序里加一个ECHO包,让程序在一定的间隔里发送特定的数据包,双方确认在线。
    如果在一定的时间内收不到,则断开。我现在就是这样做的。