言成言成啊 | Kit Chen's Blog

记录实现socket聊天室的过程

2020-01-07

整了一天,思路写得乱七八糟,最后把所有代码推翻重写。

为了让思路能够清晰一点,还特意把服务端跟客户端进行交互的过程图给画了下来。

最后,按着这个图,慢慢地研究出来了。

附上效果图。

看上去很完美了吧!

但是!

如果此时有任意一个客户端退出,服务端就会报错Connection reset,出现这个问题,是因为客户端关闭了连接,但是此时的服务端,还在读取数据,由此导致了错误(我是这样理解的)。

那么,如何让服务端判断客户端关闭连接了呢?并在客户端关闭的时候,加上一句提示xxx退出聊天室

360了一下,发现需要用到java心跳技术。

我要去学啦(此时时间2020-1-5 20:43)

发现根本不是心不心跳的问题(2020-1-7 21:14)

今天终于整明白了。

参考文章关于客户端断开连接后服务器抛出异常Connection reset

java.net.SocketException:Connection reset原因:

客户端关闭后,socket断开了,但是服务器为客户端开启的线程还在执行。所以要处理一下异常。

在为客户端开启的线程里面定义一个布尔型变量,isOnline=true,在为客户端监听时while(true)修改为while(isOnline),如果出现异常,即客户端退出,isOnline赋值为false

参考文章socket客户端异常关闭,服务端解决方案

java.net.SocketException:Socket is closed原因:

服务端不知道客户端socket已经关闭,如果继续发送数据,可能导致发送如上关闭异常。如果有多个客户端长连接给服务端建立,异常处理不恰当的话,还可能引起下次发送异常关闭情况。

socket客户端端来之后,回调服务端socket,这时服务端发现输入流的长度为-1,这时首先需要关闭客户端socket,然后把该socket从发送列表中删除。

具体解决方案:

  1. 检查是否断开
1
2
3
if(in.read(b,0,len)==-1){
break;
}
  1. 关闭客户端socket并且移除发送客户端socket
1
2
3
4
5
6
try{
//关闭socket
//从列表中删除socket
}catch(IOException e){
e.printStackTrace();
}

最后的运行结果:

开源代码下载

阅读量