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對象,連接斷開時,在

清除這個對象即可。自己立馬進行嘗試,修改程式碼,打包,發布,測試,問題解決。

參考博文 //blog.csdn.net/canot/article/details/52495333

 

最後說明一點: CopyOnWriteArrayList是執行緒安全的。介紹可以參考文章 

//www.cnblogs.com/xiaolovewei/p/9142046.html