如何获知socket client端已经断开连接

gong_max 2009-12-15 01:51:34
我做socket服务端,监测client端传过来的数据。如果一个client连接过来,我接手之后分给他一个线程。如果它断开连接之后我要把这个socket关掉,把这个线程释放出来。

但我如何判断对方的client端是否已经断开连接??
...全文
783 16 打赏 收藏 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
gong_max 2009-12-16
  • 打赏
  • 举报
回复
谢谢大家
2到20个英文 2009-12-15
  • 打赏
  • 举报
回复
一楼的
我们项目中就是这样处理滴,心跳
zabaglione 2009-12-15
  • 打赏
  • 举报
回复
mark 一下
zfangla 2009-12-15
  • 打赏
  • 举报
回复
呵呵, 呵呵, 小的不才... 各路高手承让了...
pasband 2009-12-15
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 gong_max 的回复:]
引用 7 楼 baishengjie 的回复:
捕获异常处理就可以了。
我用C#写过一个小例子,当时的处理方法是:把监听到得所有客户端保存在一个容器中,发送的时候遍历容器进行发送,就在发送的过程中try{}catch(){},如果对容器中某个客户端发送时报异常就能说明没有连接了,这时lz就可以进行想要的操作了

但是这种异常是在发送数据的时候才会抛出,我现在的情况是要收到对方的信息才会发送响应信息,但是不知道它什么时候会发过来,所以一直在阻塞这个输入流。如果那边断掉了而我这边不关闭这个连接,那么这个连接一直在阻塞而不能回收利用。
[/Quote]

试了下,确实client端在某些情况下断开,server端是不会有异常的,
可以考虑1楼的方式
深山老叔 2009-12-15
  • 打赏
  • 举报
回复
同意一楼的做法,比较实际可行。
gong_max 2009-12-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 baishengjie 的回复:]
捕获异常处理就可以了。
我用C#写过一个小例子,当时的处理方法是:把监听到得所有客户端保存在一个容器中,发送的时候遍历容器进行发送,就在发送的过程中try{}catch(){},如果对容器中某个客户端发送时报异常就能说明没有连接了,这时lz就可以进行想要的操作了
[/Quote]
但是这种异常是在发送数据的时候才会抛出,我现在的情况是要收到对方的信息才会发送响应信息,但是不知道它什么时候会发过来,所以一直在阻塞这个输入流。如果那边断掉了而我这边不关闭这个连接,那么这个连接一直在阻塞而不能回收利用。
ruiwu123 2009-12-15
  • 打赏
  • 举报
回复
一楼的才是正解,相对来说是比较符合现实的
pasband 2009-12-15
  • 打赏
  • 举报
回复
catch IOException
baishengjie 2009-12-15
  • 打赏
  • 举报
回复
捕获异常处理就可以了。
我用C#写过一个小例子,当时的处理方法是:把监听到得所有客户端保存在一个容器中,发送的时候遍历容器进行发送,就在发送的过程中try{}catch(){},如果对容器中某个客户端发送时报异常就能说明没有连接了,这时lz就可以进行想要的操作了
hzhxxx 2009-12-15
  • 打赏
  • 举报
回复

上诉代码位于

http://blog.csdn.net/hzhxxx/archive/2009/12/09/4970196.aspx
hzhxxx 2009-12-15
  • 打赏
  • 举报
回复
/**
* 接收内核 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;
}
gong_max 2009-12-15
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 zfangla 的回复:]
首先CLIENT断开有很多种情况, 比如正常发出断开的消息, 比如网络异常断开, 比如CLIENT端直接无响应了... 这些都应该认为连接断开了.

所以行业中处理这些情况的一个通用方法是, 使用心跳检测. 每隔10秒SERVER发一个心跳包给CLIENT, 让CLIENT回应, 如果连续5次不回应, 就认为CLIENT断开了, 就关连接释放线程吧
[/Quote]
也就是说在client异常断开的情况下,server端是无法获知的。这也对,因为双方不通讯就不知道是否连接。
谢谢蝈蝈
kevin luan 2009-12-15
  • 打赏
  • 举报
回复
同意一楼说法
Marty束 2009-12-15
  • 打赏
  • 举报
回复
socket编程是基于tcp协议的,记得以前做J2ME做过,J2SE没有做过,帮你顶下吧
zfangla 2009-12-15
  • 打赏
  • 举报
回复
首先CLIENT断开有很多种情况, 比如正常发出断开的消息, 比如网络异常断开, 比如CLIENT端直接无响应了... 这些都应该认为连接断开了.

所以行业中处理这些情况的一个通用方法是, 使用心跳检测. 每隔10秒SERVER发一个心跳包给CLIENT, 让CLIENT回应, 如果连续5次不回应, 就认为CLIENT断开了, 就关连接释放线程吧

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧