WebSocketConfig配置类
@Configuration
public class WebSocketConfig {
/**
* 注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Autowired
public void setMessageService(UserInfoServiceI userInfoService){
WebSocketController.userInfoService = userInfoService;
}
}
WebSocket类
@Component
@ServerEndpoint(value = "/websocket/{id}")
public class WebSocketController {
private static final Logger logger = Logger.getLogger(WebSocketController.class);
public static UserInfoServiceI userInfoService;
/**
* 客户端ID
*/
private String id = "";
/**
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
private Session session;
/**
* 记录当前在线连接数(为保证线程安全,须对使用此变量的方法加lock或synchronized)
*/
private static int onlineCount = 0;
/**
* 用来存储当前在线的客户端(此map线程安全)
*/
private static ConcurrentHashMap<String, WebSocketController> webSocketMap = new ConcurrentHashMap<>();
// /**
// * 用于存储用户
// */
private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();
/**
* 连接建立成功后调用
*/
@OnOpen
public void onOpen(@PathParam(value = "id") String id, Session session) {
//设置长连接时间1小时
session.setMaxIdleTimeout(3600000);
这里展示部分代码
部署在tomcat上,没有用nginx代理
下面报错的地方在onError方法里面
@OnError
public void onError(Session session, Throwable error) {
logger.error("onError==WebSocket发生错误id["+session.getId()+"]",error);
}
java.io.EOFException
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1301)
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1234)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:75)
at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:183)
at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:162)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:156)
at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:60)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:59)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1629)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
据网上查询到的解释
1,如果一端的Socket被关闭(或主动关闭,或因为异常退出而 引起的关闭),另一端仍发送数据,发送的第一个数据包引发该异常(Connect reset by peer)。
Socket默认连接60秒,60秒之内没有进行心跳交互,即读写数据,就会自动关闭连接。
2,一端退出,但退出时并未关闭该连接,另一端如果在从连接中读数据则抛出该异常(Connection reset)。
感觉比较靠谱但是解决办法
解决办法:
1、设置tomcat最大连接数,最大等待数,最大线程数
2、服务端开启线程每20秒群发消息
3、Tomcat Session过期时间
前两个都是修改tomcat的配置文件conf
在server.xml中定义context时采用如下定义:
xml 代码
都试过了还是不行