如何获知socket client端已经断开连接 我做socket服务端,监测client端传过来的数据。如果一个client连接过来,我接手之后分给他一个线程。如果它断开连接之后我要把这个socket关掉,把这个线程释放出来。但我如何判断对方的client端是否已经断开连接?? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 首先CLIENT断开有很多种情况, 比如正常发出断开的消息, 比如网络异常断开, 比如CLIENT端直接无响应了... 这些都应该认为连接断开了.所以行业中处理这些情况的一个通用方法是, 使用心跳检测. 每隔10秒SERVER发一个心跳包给CLIENT, 让CLIENT回应, 如果连续5次不回应, 就认为CLIENT断开了, 就关连接释放线程吧 socket编程是基于tcp协议的,记得以前做J2ME做过,J2SE没有做过,帮你顶下吧 也就是说在client异常断开的情况下,server端是无法获知的。这也对,因为双方不通讯就不知道是否连接。谢谢蝈蝈 /** * 接收内核 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; } 上诉代码位于http://blog.csdn.net/hzhxxx/archive/2009/12/09/4970196.aspx 捕获异常处理就可以了。我用C#写过一个小例子,当时的处理方法是:把监听到得所有客户端保存在一个容器中,发送的时候遍历容器进行发送,就在发送的过程中try{}catch(){},如果对容器中某个客户端发送时报异常就能说明没有连接了,这时lz就可以进行想要的操作了 试了下,确实client端在某些情况下断开,server端是不会有异常的,可以考虑1楼的方式 我的多线程发牌程序错在哪里 有关控制器的问题 一个线程的问题 如何理解Class类的实体的概念? 送出100分,问几个问题! 下面的语句是什么意思?? 急啊!!!!:如何让Jtree点击右键的时候菜单显示在选中的item上面!!!! 如何把HTML中文字提取出来??高手请进 局域网传输文件 关于电子白板中橡皮筋算法的实现 [Java]String.format 里的 %s 合并问题! 一般的java代码,怎样用Java -jar 运行??
谢谢蝈蝈
* 接收内核 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;
}
上诉代码位于http://blog.csdn.net/hzhxxx/archive/2009/12/09/4970196.aspx
我用C#写过一个小例子,当时的处理方法是:把监听到得所有客户端保存在一个容器中,发送的时候遍历容器进行发送,就在发送的过程中try{}catch(){},如果对容器中某个客户端发送时报异常就能说明没有连接了,这时lz就可以进行想要的操作了
试了下,确实client端在某些情况下断开,server端是不会有异常的,
可以考虑1楼的方式