我做socket服务端,监测client端传过来的数据。如果一个client连接过来,我接手之后分给他一个线程。如果它断开连接之后我要把这个socket关掉,把这个线程释放出来。但我如何判断对方的client端是否已经断开连接??

解决方案 »

  1.   

    首先CLIENT断开有很多种情况, 比如正常发出断开的消息, 比如网络异常断开, 比如CLIENT端直接无响应了... 这些都应该认为连接断开了.所以行业中处理这些情况的一个通用方法是, 使用心跳检测. 每隔10秒SERVER发一个心跳包给CLIENT, 让CLIENT回应, 如果连续5次不回应, 就认为CLIENT断开了, 就关连接释放线程吧
      

  2.   

    socket编程是基于tcp协议的,记得以前做J2ME做过,J2SE没有做过,帮你顶下吧
      

  3.   

    也就是说在client异常断开的情况下,server端是无法获知的。这也对,因为双方不通讯就不知道是否连接。
    谢谢蝈蝈
      

  4.   

    /**
     * 接收内核 socket 缓冲区的数据到连接自建立的缓冲区(支持自动增长)
     * 
     * @param in
     *            实际接收到的数据包队列
     * @return PACKET_ERROR 表示对方关闭连接, PACKET_FULL 表示数据发送完毕, PACKET_LESS
     *         表示数据继续接收.
     * @see #parse(Vector)
     */
    public Define.DataRecvStatus recv(Vector<byte[]> in) throws Exception {
    Define.DataRecvStatus result = null;
    result = Define.DataRecvStatus.PACKET_FULL;
    int received = 0;
    m_recvbuff.limit(this.m_recvcapacity);
    m_onerecvbuff.clear();
    while (received < m_onerecvbuff.limit() && m_onerecvbuff.hasRemaining()) {
    try {
    int len = 0;
    len = m_socketchannel.read(m_onerecvbuff);
    // 通道 数据被读取完全,是否表示这个连接已经没有数据了
    if (len < 0) {
    // 一般是-1,可以认为连接被对方关闭
    result = Define.DataRecvStatus.PACKET_ERROR;
    break;
    } else if (len == 0) {
    // 如果每次都是 0,会是什么情况
    result = Define.DataRecvStatus.PACKET_LESS;
    break;
    } else {
    received += len;
    result = Define.DataRecvStatus.PACKET_LESS;
    }
    } catch (NotYetConnectedException e) {
    result = Define.DataRecvStatus.PACKET_ERROR;
    logger.error("oops, got an exception: ", e);
    break;
    } catch (ClosedByInterruptException e) {
    result = Define.DataRecvStatus.PACKET_ERROR;
    logger.error("oops, got an exception: ", e);
    break;
    } catch (AsynchronousCloseException e) {
    result = Define.DataRecvStatus.PACKET_ERROR;
    logger.error("oops, got an exception: ", e);
    break;
    } catch (ClosedChannelException e) {
    result = Define.DataRecvStatus.PACKET_ERROR;
    logger.error("oops, got an exception: ", e);
    //logger.error("cid:" + this.m_cid);
    break;
    } catch (IOException e) {
    result = Define.DataRecvStatus.PACKET_ERROR;
    logger.error("oops, got an exception: ", e);
    break;
    }
    } m_onerecvbuff.flip();
    if (m_onerecvbuff.limit() > m_recvbuff.remaining()) {
    // 继续扩大接收缓冲区
    m_recvbuff.flip();
    byte[] bytes = new byte[m_recvbuff.limit()];
    m_recvbuff.get(bytes, 0, m_recvbuff.limit());
    m_recvcapacity *= 2;
    m_recvbuff = ByteBuffer.allocate(m_recvcapacity);
    m_recvbuff.put(bytes);
    } // 合并本次实际接收到的数据
    m_recvbuff.put(m_onerecvbuff); // 如果数据没有接收完整,对方关闭连接,最后一段不完整数据可能被丢弃
    // 如果解析协议发生错误,等同与连接被关闭,不过是服务器主动关闭
    if (result == Define.DataRecvStatus.PACKET_ERROR) {
    if (received > 0) {
    parse(in);
    }
    } else {
    if (received > 0) {
    result = parse(in);
    }
    } // 确实接收到了数据,才设置时间
    if (received > 0) {
    m_lasttime = new DateTime().allmillisecond();
    } return result;
    }
      

  5.   


    上诉代码位于http://blog.csdn.net/hzhxxx/archive/2009/12/09/4970196.aspx
      

  6.   

    捕获异常处理就可以了。
    我用C#写过一个小例子,当时的处理方法是:把监听到得所有客户端保存在一个容器中,发送的时候遍历容器进行发送,就在发送的过程中try{}catch(){},如果对容器中某个客户端发送时报异常就能说明没有连接了,这时lz就可以进行想要的操作了
      

  7.   


    试了下,确实client端在某些情况下断开,server端是不会有异常的,
    可以考虑1楼的方式