Java网络多线程开发:java.io.EOFException

在实现韩顺平Java的多用户即使通信系统实战项目中:

对于客户端线程的停止,老韩是向服务器端发送一个消息对象,提示服务器端进行资源释放(包含线程集合资源以及socket连接断开)。对于客户端部分,使用如下代码:

// 编写一个方法,退出客户端,并给服务器端发送一个退出系统的消息对象
public void logout() {
Message message = new Message();
message.setMesType(MessageType.MESSAGE_CLEAR_EXIT);
message.setSender(u.getUserId());
// 发送message对象
try {
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(message);
System.out.println(TimeGet.getLocalTime() + " 用户:" + u.getUserId() + " 退出系统 ");
System.exit(0); // 结束虚拟机,客户端
} catch (IOException e) {
e.printStackTrace();
}
}

然而,当登录用户成功后,再进行退出系统操作,会发生java.io.EOFException:

定位到提示错误的代码行,发现这个错误其实是在说明客户端监听服务器端Message的线程依然在进行中:

public class ClientConnectServerThread extends Thread{
private Socket socket;//该线程需要持有Socket public ClientConnectServerThread(Socket socket) {
this.socket = socket;
} @Override
public void run() {
while (true) {
try {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); //报错的代码行
Message ms = (Message) ois.readObject();

解决方法:

服务器端在接收到客户端发来的退出系统消息后,向客户端发出回应,客户端监听到服务器端发来的回应后,立马取消监听。

服务器端:收到客户端退出系统消息后,向客户端回应

            .....................
} else if (message.getMesType().equals(MessageType.MESSAGE_CLEAR_EXIT)) { // 客户端要退出系统
// 解决方案==============
Message message2 = new Message();
//设置当前message1是一条返回用户列表信息的信息对象
message2.setMesType(MessageType.MESSAGE_CLEAR_EXIT);
message2.setGetter(message.getSender());
// 将message对象返回给客户端
ObjectOutputStream oos1 = new ObjectOutputStream(socket.getOutputStream());
oos1.writeObject(message2);
// ========================= ManageClientThreads.removeClientThread(userId); // 释放服务器线程库资源
socket.close(); // 关闭连接
break; // 退出线程
} else {
..........

客户端:很简单,break,结束监听进程

                else if (ms.getMesType().equals(MessageType.MESSAGE_CLEAR_EXIT)) {
// ManageClientConnectServerThread.removeThreadSource(ms.getGetter());
// socket.close();
break;
}

客户端完整的监听服务器端的代码:

public class ClientConnectServerThread extends Thread{
private Socket socket;//该线程需要持有Socket public ClientConnectServerThread(Socket socket) { //构造器
this.socket = socket;
} @Override
public void run() {
while (true) {// 线程需要不停地监听服务器是否发送了Message
try {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Message ms = (Message) ois.readObject();// 如果服务器没有发送Message对象,线程会阻塞在这里 // 根据服务器返回message对象的类型,进行相应的处理
if (ms.getMesType().equals(MessageType.MESSAGE_RET_ONLINE_FRIEND)) {
String[] mesArray = ms.getComment().split(" "); // 服务器端每一条数据后,都用空格符进行区分
for (String s : mesArray) {
System.out.println(s);
}
}
else if (ms.getMesType().equals(MessageType.MESSAGE_CLEAR_EXIT)) {
// ManageClientConnectServerThread.removeThreadSource(ms.getGetter());
// socket.close();
break;
}
else {
System.out.println("其他消息暂时不处理!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
} public Socket getSocket(){
return socket;
}
}

最新文章

  1. 全网独家MongoDB Certified DBA Associate考试认证视频
  2. NB-IoT的相关资料整理(基本概念,技术优势,典型案例和当前的进展)
  3. MySQL判断字段值来确定是否插入新记录
  4. 关于iOS地图定位中点击设置->隐私->定位服务 闪退问题
  5. CSS 魔法系列:纯 CSS 绘制基本图形(圆、椭圆等)
  6. Python中的编码
  7. OC第九节——协议与代理
  8. JavaScript及其异步实现续:Promise让一切更简单
  9. NLTk
  10. 自学Linux命令的四种方法
  11. asp.net 控件 导出 excel
  12. 【转】Java基本数据类型
  13. PHP获取文件的绝对路径
  14. 修改mysqlcharacter_set_database与character_set_server的默认编码(windows环境)
  15. 第1章 从开机加电到main函数之前的过程
  16. fastjson的JSONArray和JSONObject
  17. eclipse svn 忽略 target目录
  18. csharp: using HtmlAgilityPack and ScrapySharp reading Url find text
  19. Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1) B - Bear and Friendship Condition 水题
  20. linux中安装typecho的pathinfo配置

热门文章

  1. [luogu5537]系统设计
  2. ES6学习 第五章 正则的扩展
  3. CSS动画--让div动起来
  4. Mac Maven 安装及配置
  5. CF605E Intergalaxy Trips
  6. CF1208H Red Blue Tree
  7. 使用bioawk对基因组fasta序列ID(染色体/scaffold名称)排序?
  8. nginx 文件目录页面
  9. 一个神奇的JS混淆,JSFuck!
  10. ceph块存储场景