1. 程式人生 > 其它 >The WebSocket session [0] has been closed and no method (apart from close()) may be called on a closed session-ConcurrentHashMap使用在webSocket中採的坑

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