The WebSocket session [0] has been closed and no method (apart from close()) may be called on a clos
Posted 遇见美好,遇见妳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了The WebSocket session [0] has been closed and no method (apart from close()) may be called on a clos相关的知识,希望对你有一定的参考价值。
一、问题由来
现在开发的一个项目中使用webSocket这个技术和Unity客户端程序进行联动操作,因为socket连接相对来说比http请求连接更加的快速,而且是
一个长链接,方便于这个项目进行其他的业务操作,最终将这个技术应用在了项目中。在使用过程中出现一个问题,就是客户端在断开之后,再次
连接时出现问题,错误信息如下
大致意思就是创建的那个WebSocketServer对象为null,然后就一直报错。由于这个项目的特殊性,客户端只有一个,因此服务端的
WebSocketServer对象也只有一个,创建连接时会创建一个WebSocketServer对象,并且将它存储在ConcurrentHashMap集合中,为
了出现线程安全的问题,因此选择这个集合。连接断开的时候,清除这个集合中的元素。
二、问题分析
对于出现的这个问题,我就很纳闷了,怎么一般情况下使用的时候都好好的,可一段断开之后再次连接时就出现问题呢?这到底是什么原因呢?
自己做过一种假设,服务端的WebSocketServer对象只有一个,如果不清除这个对象行不行呢?带着这样的疑问,我开始各种尝试。
private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
三、解决方案
尝试解决办法一:服务端连接断开的时候,不清除ConcurrentHashMap集合中保存的WebSocketServer元素,重新打包发布,测试,结果不行。
继续进行分析:服务端的WebSocketServer只有一个,可是连接确有多个,会不会是连接session没有正确清除或者关闭导致的问题呢?
private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();
尝试解决办法二:将创建的这集合在服务连接时,加入到这个集合中,在连接关闭时,从集合中进行清除。继续打包,发布、测试,结果不行。
可是这时报了一个新的错误,不在是webSocketServer为null了,而是
The WebSocket session [0] has been closed and no method (apart from close()) may be called on a closed session 这个错误信息。最起码错误
信息已经不一样了。大致意思就是 WebSocket会话已关闭,不能对已关闭的会话调用任何方法(close()除外),新的错误信息让我很是高兴,
感觉总算是有点起色了。自己带着这个问题去必应里面进行搜索,找到了问题的原因。
导致这个问题的原因是: 使用ConcurrentHashMap这个集合的时候,自己认为它解决了线程安全的问题,可是出现一个新的问题,就是清除这个集合
的时候,连接信息session没有被清除,因此导致出现这个奇怪的问题。文中也提供了解决方案,
尝试解决办法三:解决办法为使用CopyOnWriteArraySet这个集合来存储每一次有连接加入时创建的新的WebSocketServer对象,连接断开时,在
清除这个对象即可。自己立马进行尝试,修改代码,打包,发布,测试,问题解决。
参考博文 https://blog.csdn.net/canot/article/details/52495333
最后说明一点: CopyOnWriteArrayList是线程安全的。介绍可以参考文章
https://www.cnblogs.com/xiaolovewei/p/9142046.html
javax.websocket.Session API
【中文标题】javax.websocket.Session API【英文标题】:javax.websocket.Session api 【发布时间】:2015-04-21 11:16:08 【问题描述】:我需要检索会话 ID,但 Eclipse 告诉我 “方法 getId() 未定义 Session 类型”
这里是标题:
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
这里是错误:
@OnOpen
public void onOpen(Session session)
System.out.println(session.getId() + " has opened a connection");
//session.getId() is undefined.
try
session.getBasicRemote().sendText("Connection Established");
//same here getBasicRemote is undefined
catch (IOException ex)
ex.printStackTrace();
我使用 gradle 构建我的项目。我想我包括了所有的依赖。
dependencies
compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
compile 'org.glassfish.main.extras:glassfish-embedded-all:4.0-b72'
compile 'javax:javaee-api:7.0'
testCompile group: 'junit', name: 'junit', version: '4.+'
然后我运行 gradle eclipse。但是 getId() 仍然未定义。
如果有人有想法!谢谢。
【问题讨论】:
【参考方案1】:覆盖 javax websocket api 的是 'org.glassfish.main.extras:glassfish-embedded-all:4.0-b72' 库。
改为使用 org.glassfish.main.extras:glassfish-embedded-all:4.1。 很奇怪。
【讨论】:
以上是关于The WebSocket session [0] has been closed and no method (apart from close()) may be called on a clos的主要内容,如果未能解决你的问题,请参考以下文章
基于tomcat 7.0.68 的websocket 实现,及通过 HttpSessionId 实现websocket session 共享
基于tomcat 7.0.68 的websocket 实现,及通过 HttpSessionId 实现websocket session 共享