学习通项目完成的差不多了
解决抢答问题的时候出了点问题,不知道应该怎么实现,后来新建了个socket包换了个端口专门做实时通讯,代码如下
new Thread(()->{
try (ServerSocket realtimeServerSocket = new ServerSocket(9999)) {
System.out.println("实时提示服务器已启动,监听端口:" + 9999);
while (true) {
Socket realtimeSocket = realtimeServerSocket.accept();
new Thread(()-> {
Integer id = null;
try {
ObjectInputStream realtimein = new ObjectInputStream(realtimeSocket.getInputStream());
ObjectOutputStream realtimeout = new ObjectOutputStream(realtimeSocket.getOutputStream());
Msg now = new Msg();
while (true) {
now = (Msg) realtimein.readObject();
switch (now.getHappen()) {
case 999:
break;
case 1000: // 心跳消息
Integer clientId =id; // 从消息或连接中获取客户端ID
lastHeartbeatTimeMap.put(clientId, System.currentTimeMillis()); // 更新最后心跳时间
stringToSocketMap.put(clientId, realtimeSocket);
startHeartbeatChecker();
System.out.println("ok");
break;
case 1001:
User user1 = (User) now.getData();
id = user1.getId();
stringToSocketMap.put(user1.getId(), realtimeSocket);
idToObjectOutputStreamMap.put(user1.getId(),realtimeout);
for (Integer key : stringToSocketMap.keySet()) {
System.out.println("Key: " + key);
}
break;
case 1002:
Rushanswer rushanswer=(Rushanswer)now.getData();
Integer classid=rushanswer.getClassid();
System.out.println(classid);
// 创建一个容器来存储student_id
List<Integer> studentIds = new ArrayList<>();
// 连接到数据库并执行查询(这里假设您已经有了一个getConnection方法)
try (Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT student_id FROM student_class WHERE class_id = ?")) {
stmt.setInt(1, classid);
ResultSet rs = stmt.executeQuery();
// 遍历结果集,将student_id添加到容器中
while (rs.next()) {
studentIds.add(rs.getInt("student_id"));
System.out.println(rs.getInt("student_id"));
}
} catch (SQLException e) {
// 处理数据库查询异常
e.printStackTrace();
}
// 遍历容器中的student_id,并找到对应的Socket发送消息
for (Integer studentId : studentIds) {
Socket targetSocket = stringToSocketMap.get(studentId);
//System.out.println("87");
if (targetSocket != null && !targetSocket.isClosed()) {
// try (ObjectOutputStream outa = new ObjectOutputStream(socket.getOutputStream())) {
// // 创建一个消息对象,设置适当的数据和happen值
Msg msg = new Msg();
// 假设您想发送rushanswer对象或者与抢答相关的其他数据
// msg.setData(...); // 设置要发送的数据
msg.setHappen(10001); // 设置适当的happen值
msg.setData(rushanswer);
System.out.println("78");
// // 发送消息
// outa.writeObject(msg);
// outa.flush();
// } catch (IOException e) {
// //处理发送消息时可能出现的异常
// e.printStackTrace();
// // 可能需要从stringToSocketMap中移除该socket,因为它可能已关闭或无效
// //stringToSocketMap.remove(studentId);
// }
if (targetSocket == realtimeSocket) { // 确保我们不会向当前线程关联的socket发送消息(除非这是意图)
// 使用当前线程的realtimeout流发送消息
realtimeout.writeObject(msg);
realtimeout.flush();
} else if (targetSocket != null && !targetSocket.isClosed()) {
// 如果需要向其他客户端发送消息,你需要有到那个客户端的OutputStream的引用
// 这通常意味着你需要维护一个到所有客户端OutputStream的映射,而不仅仅是Socket
// 在这个简化的示例中,我们假设你有这样的映射
ObjectOutputStream targetOutputStream =idToObjectOutputStreamMap.get(studentId); // 获取到targetSocket的OutputStream
targetOutputStream.writeObject(msg);
targetOutputStream.flush();
}
} else {
// socket为null或已关闭,可以记录日志或执行其他操作
}
}
break;
}
}
} catch (IOException e) {
stringToSocketMap.remove(id);
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}).start();
这是服务器代码,下面是客户端代码
new Thread(()->{
try {
clientSocket1 = new Socket("localhost", 9999);
outnow = new ObjectOutputStream(clientSocket1.getOutputStream());
innow = new ObjectInputStream(clientSocket1.getInputStream());
RushanswerController.setin(innow);
RushanswerController.setout(outnow);
Msg msg =new Msg();
msg.setHappen(1001);
msg.setData(DengluController.alluser);
outnow.writeObject(msg);
outnow.flush();
Timer heartbeatTimer = new Timer();
heartbeatTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
// 发送心跳消息
Msg heartbeatMsg = new Msg();
heartbeatMsg.setHappen(1000); // 心跳消息的happen值
outnow.writeObject(heartbeatMsg);
outnow.flush();
} catch (IOException e) {
// 处理异常,可能是连接已关闭
e.printStackTrace();
// 停止心跳定时器并尝试重新连接服务器
heartbeatTimer.cancel();
// ... 重新连接逻辑 ...
}
}
}, 0, 10 * 1000); // 立即开始,然后每隔HEARTBEAT_INTERVAL秒发送一次心跳
while (true) { // 持续监听服务器消息
msg = (Msg) innow.readObject(); // 读取消息
switch (msg.getHappen()) {
case 10001: // 假设这是表示抢答开始的响应消息类型
System.out.println("sdfhukis");
break;
case 10002: // 其他消息类型...
// 处理其他消息...
break;
// ... 其他case语句处理其他消息类型 ...
default:
// 处理未知消息类型或错误情况
break;
}
}
} catch (IOException | ClassNotFoundException e) {
// 处理异常,例如连接断开或消息格式错误
e.printStackTrace();
// 可能需要重新连接服务器或执行其他恢复操作
}
}).start();