The WebSocket session [0] has been closed and no method (apart from close()) may be called on a closed session-ConcurrentHashMap使用在webSocket中采的坑


一、問題由來

現在開發的一個項目中使用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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM