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