java.io.EOFException at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer
如题,网上找了相关资料查明是websocket连接超时的问题。使用了反向代理,因此超过60S没有数据传输的连接会断开。
把代理的那个超时时间设置长一点,无限长。你开什么玩笑!那还代理个啥玩意。
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。解决方法一:后台写个定时程序每<60s频率给前端的socket发个消息就好了。
import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import javax.annotation.Resource; /** * @Auther: lanhaifeng * @Date: 2019/5/16 0016 14:29 * @Description:webSocket定时发送消息类 * @statement: 以<60s的频率发送给websocket连接的对象,以防止反向代理的60s超时限制 */ @Configuration //1.主要用于标记配置类,兼备Component的效果。 @EnableScheduling // 2.开启定时任务 public class SaticScheduleTask { @Resource private WebSocketServer webSocketServer; //3.添加定时任务 //@Scheduled(cron = "0/5 * * * * ?") //或直接指定时间间隔,例如:5秒 @Scheduled(fixedRate=58*1000) private void configureTasks() throws Exception{ webSocketServer.sendMessage("连接成功"); } }
WebSocketServer
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; /** * @Auther: lanhaifeng * @Date: 2018/11/6 0006 17:59 * @Description: * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端, * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端 * @ServerEndpoint 可以把当前类变成websocket服务类 */ @ServerEndpoint("/websocket/{sid}") @Component public class WebSocketServer { private static Logger logger = LoggerFactory.getLogger(WebSocketServer.class); //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; //接收sid private String sid=""; /** * 连接建立成功调用的方法*/ @OnOpen public void onOpen(Session session, @PathParam("sid") String sid) { this.session = session; webSocketSet.add(this); //加入set中 addOnlineCount(); //在线数加1 logger.info("有新窗口开始监听:"+sid+",当前在线人数为" + getOnlineCount()); this.sid=sid; try { sendMessage("连接成功"); } catch (IOException e) { logger.error("websocket IO异常"); } } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { webSocketSet.remove(this); //从set中删除 subOnlineCount(); //在线数减1 logger.info("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息*/ @OnMessage public void onMessage(String message, Session session) { logger.info("收到来自窗口"+sid+"的信息:"+message); //群发消息 for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } /** * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { logger.error("发生错误"); error.printStackTrace(); } /** * 实现服务器主动推送 */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } /** * 群发自定义消息 * */ public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException { logger.info("推送消息到窗口"+sid+",推送内容:"+message); for (WebSocketServer item : webSocketSet) { try { //这里可以设定只推送给这个sid的,为null则全部推送 if(sid==null) { item.sendMessage(message); }else if(item.sid.equals(sid)){ item.sendMessage(message); } } catch (IOException e) { continue; } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; } public Session getSession() { return session; } public void setSession(Session session) { this.session = session; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } }
解决方法二:既然后台能发消息,前端不照样能发吗?而且上面后台发消息还存在多线程的问题以及各种未知BUG。
于是果断前端 js 使用
setInterval(function () { socket.send("连接成功"); },58*1000);

更多精彩