如果网络客户端的网线拔掉,
好像只能通过心跳包的方式检测实现???我隔一段时间去select这个客户端连接状态,
发现还是可以写、也没有异常。这个问题该怎么解决???

解决方案 »

  1.   

    做个心跳包
    或者设置socket的keepalive属性
      

  2.   

    设置SOCKET的 Keep Alive选项代码参考如下://程序如下所示: //以下宏需要自定义 
    #define  SIO_RCVALL  IOC_IN | IOC_VENDOR | 1 
    #define  SIO_RCVALL_MCAST  IOC_IN | IOC_VENDOR | 2 
    #define  SIO_RCVALL_IGMPMCAST  IOC_IN | IOC_VENDOR | 3 
    #define  SIO_KEEPALIVE_VALS  IOC_IN | IOC_VENDOR | 4 
    #define  SIO_ABSORB_RTRALERT  IOC_IN | IOC_VENDOR | 5 
    #define  SIO_UCAST_IF  IOC_IN | IOC_VENDOR | 6 
    #define  SIO_LIMIT_BROADCASTS  IOC_IN | IOC_VENDOR | 7 
    #define  SIO_INDEX_BIND  IOC_IN | IOC_VENDOR | 8 
    #define  SIO_INDEX_MCASTIF  IOC_IN | IOC_VENDOR | 9 
    #define  SIO_INDEX_ADD_MCAST  IOC_IN | IOC_VENDOR | 10 
    #define  SIO_INDEX_DEL_MCAST  IOC_IN | IOC_VENDOR | 11 //自定义的结构体 
    typedef struct tcp_keepalive 

        u_long onoff; 
        u_long keepalivetime; 
        u_long keepaliveinterval; 
    }TCP_KEEPALIVE,*PTCP_KEEPALIVE; int main(int argc, char* argv[]) 

        WSADATA wsaData = {0}; 
        if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) 
        { 
            cout < < "WSAStartup failed. error code = " < < WSAGetLastError() < < endl; 
          
            cout < < "Press any key exit." < < endl; 
            getch(); 
            return 0; 
        }     SOCKET s = INVALID_SOCKET; 
        
        // 
        s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
        if (s == INVALID_SOCKET) 
        { 
            cout < < "socket failed. error code = " < < WSAGetLastError() < < endl; 
        } 
        else 
        { 
            int iKeepAlive = -1; 
            int iOptLen = sizeof(iKeepAlive); 
    //取得SO_KEEPALIVE选项信息 
            if (getsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&iKeepAlive, &iOptLen) == SOCKET_ERROR) 
            { 
                cout < < "getsockopt failed. error code = " < < WSAGetLastError() < < endl; 
            } 
            else 
            { 
                iKeepAlive = 1; 
        //这里设置成功的Keep Alive是针对操作系统的所有网络通信 
                if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&iKeepAlive, iOptLen) == SOCKET_ERROR) 
                { 
                    cout < < "setsockopt failed. error code = " < < WSAGetLastError() < < endl; 
                } 
                else 
                { 
                    iKeepAlive = -1; 
                    if (getsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&iKeepAlive, &iOptLen) == SOCKET_ERROR) 
                    { 
                        cout < < "getsockopt failed. error code = " < < WSAGetLastError() < < endl; 
                    } 
                    else if (iKeepAlive == 1) 
                    { 
                        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; 
                        inKeepAlive.keepalivetime = 3; 
                        
          //为选定的SOCKET设置Keep Alive,成功后SOCKET可通过Keep Alive自动检测连接是否断开 
                        if (WSAIoctl(s, SIO_KEEPALIVE_VALS, 
                            (LPVOID)&inKeepAlive, ulInLen, 
                            (LPVOID)&outKeepAlive, ulOutLen, 
                            &ulBytesReturn, NULL, NULL) == SOCKET_ERROR) 
                        { 
                            cout < < "WSAIoctl failed. error code = " < < WSAGetLastError() < < endl; 
                        } 
                    } 
                } 
            } 
        }     WSACleanup(); 
        cout < < "Press any key exit." < < endl; 
        getch(); 
        return 0; 

      

  3.   

    设置SOCKET的 Keep Alive选项,必须是异步的服务器模式。
      

  4.   

    设置为KeepAlive选项后,如何判断断线?
      

  5.   

    6楼贴的代码是一个用于设置keep alive选项的,那么如何通过这个选项得知socket已经异常断开呢?
      

  6.   

    心跳包会产生额外的网络流量啊,
    例如:GPRS的网络心跳包流量就是可以节省的。