2015-03-12 6 views
8

मैं टॉमकैट 8.0.15, वसंत 4.1.5 का उपयोग कर रहा हूं।वेबसॉकेट रिमोट एंडपॉइंट राज्य में था [TEXT_PARTIAL_WRITING]

मैंने नीचे की तरह websocket का उपयोग करने के लिए 3 अनिवार्य कार्यों को लागू किया। यह बहुत आसान है।

private Map<String, WebSocketSession> map_users = new ConcurrentHashMap<>(); 
private Map<String, String> map_id = new ConcurrentHashMap<>(); 

public void afterConnectionEstablished(WebSocketSession wss) throws Exception { 
    map_users.put(wss.getId(), wss); 
} 

public void afterConnectionClosed(WebSocketSession wss, CloseStatus cs) throws Exception { 
    map_users.remove(wss.getId()); 

    // remove user 
    String username = map_id.get(wss.getId()); 
    if (username != null) { 
     map_id.remove(wss.getId()); 
     map_id.remove(username); 
    } 
} 

public void handleTextMessage(WebSocketSession wss, TextMessage tm) throws Exception { 
    String str = tm.getPayload(); 
    String username = ...; 

    // regist user 
    if (!map_id.get(wss.getId())) { 
     map_id.put(wss.getId(), username); 
     map_id.put(username, wss.getId()); 
    } 

    for (WebSocketSession w: map_users.values()) { 
     w.sendMessage(new TextMessage(wss.getId() + " send to " + w.getId() + ", msg:" + tm.getPayload())); 
    } 
} 

कुछ ग्राहक संदेश भेजते हैं और अन्य क्लाइंट हैंडलटेक्स्ट मैसेज द्वारा संदेश प्राप्त करते हैं।

मेरे मामले में, हैंडलटेक्स्ट मैसेज फ़ंक्शन के बिना, सर्वर प्रोग्राम क्लाइंट को एक टेक्स्ट संदेश भेजना चाहता है।

String websocketsesssion_id = map_id.get(username); 
WebSocketSession wss = map_users.get(websocketsesssion_id); 
wss.sendMessage(new TextMessage(new java.util.Date())); 

कोड से ऊपर बहुत अच्छी तरह से काम करता है (इस के लिए मैं एक WebSocketSession की ईद और map_id में उपयोगकर्ता नाम बचाया)। लेकिन जब कुछ क्लाइंट का वेबसाकेट सत्र उपयोग में है और एक साथ उपयोग करने का प्रयास करता है, तो यह त्रुटि बनाता है। इसका मतलब है 1. कुछ क्लाइंट संदेश भेजते हैं -> हैंडलटेक्स्ट मैसेज को -> क्लाइंट का वेबसाकेट सत्र का उपयोग कर रहा है 2. सर्वर प्रोग्राम उस क्लाइंट को संदेश भेजना चाहता है -> क्लाइंट के वेबसाकेट सत्र को मानचित्र से प्राप्त करें -> कोशिश करें एक ही WebSocketSession

Stacktrace:] with root cause 
java.lang.IllegalStateException: The remote endpoint was in state [TEXT_PARTIAL_WRITING] which is an invalid state for called method 
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.checkState(WsRemoteEndpointImplBase.java:1092) 
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.textPartialStart(WsRemoteEndpointImplBase.java:1050) 
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendPartialString(WsRemoteEndpointImplBase.java:218) 
    at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendText(WsRemoteEndpointBasic.java:49) 
    at org.springframework.web.socket.adapter.standard.StandardWebSocketSession.sendTextMessage(StandardWebSocketSession.java:197) 
    at org.springframework.web.socket.adapter.AbstractWebSocketSession.sendMessage(AbstractWebSocketSession.java:105) 
    at org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession.writeFrameInternal(WebSocketServerSockJsSession.java:222) 
    at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.writeFrame(AbstractSockJsSession.java:325) 
    at org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession.sendMessageInternal(WebSocketServerSockJsSession.java:212) 
    at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.sendMessage(AbstractSockJsSession.java:161) 

परिणाम के रूप में साथ संदेश भेजते हैं, WebSocketSession बंद कर दिया है और ग्राहक फिर से नया WebSocketSession खोलने के लिए है।

तो, मेरे सवाल यह है:

मैं जांच कर सकता है कि क्या WebSocketSession उपयोग में है या नहीं? (handleTextMessage समारोह के बाहर)

उत्तर

11
समस्या

है कि कई धागा सॉकेट इतने पर एक ही समय में लिखने की कोशिश:

कोशिश:

String websocketsesssion_id = map_id.get(username); 
WebSocketSession wss = map_users.get(websocketsesssion_id); 
synchronized(wss) { 
wss.sendMessage(new TextMessage(new java.util.Date())); 
} 
1

sendMessage() कॉल को सिंक्रनाइज़ जबकि ws के लिए मदद करता है:// कनेक्शन, यह wss://, i.e. SSL/TLS connection के लिए मदद नहीं करता है। यदि आप आंशिक संदेश पढ़ने के दौरान आंशिक संदेश भेजना चाहते हैं तो यह 100% विफलता है। मैंने स्प्रिंग बूट 1.4.2 रिलीज (टॉमकैट 8.5.6)

पर टॉमकैट 8.5.9 के साथ इसका परीक्षण किया है। नीचे ट्रेस स्टैक देखें।

[pool-18-thread-1] [GenericMessageEndpoint] Sending message to the endpoint: 
[pool-18-thread-2] [GenericMessageEndpoint] Sending message to the endpoint: 
[pool-18-thread-3] [GenericMessageEndpoint] Sending message to the endpoint: 

[https-jsse-nio-8443-exec-1] [FrontendWebSocketHandler] Message from 0, isLast: false, length: 16384 
[https-jsse-nio-8443-exec-1] [FrontendWebSocketHandler] Message from 0, isLast: false, length: 16384 

[pool-18-thread-3] [FrontendWebSocketHandler] Transport error. Session: StandardWebSocketSession[id=0, uri=/myt/websocket] 
java.io.IOException: java.io.IOException: Unable to wrap data, invalid status [CLOSED] 
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:315) 
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:258) 
    at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:606) 
    at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:494) 
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:313) 
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:250) 
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendPartialString(WsRemoteEndpointImplBase.java:223) 
    at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendText(WsRemoteEndpointBasic.java:49) 
    at org.springframework.web.socket.adapter.standard.StandardWebSocketSession.sendTextMessage(StandardWebSocketSession.java:197) 
    at org.springframework.web.socket.adapter.AbstractWebSocketSession.sendMessage(AbstractWebSocketSession.java:104) 
    at com.ebs.mytreasury.frontend.websocket.FrontendWebSocketHandler.send(FrontendWebSocketHandler.java:180) 
    at com.ebs.mytreasury.frontend.websocket.FrontendWebSocketHandler.send(FrontendWebSocketHandler.java:24) 
    at com.ebs.mytreasury.frontend.GenericMessageEndpoint.sendMessage(GenericMessageEndpoint.java:72) 
    at com.ebs.mytreasury.frontend.GenericMessageEndpoint.send(GenericMessageEndpoint.java:57) 
    at com.mytreasury.services.backend.MessageSender.process(MessageSender.java:24) 
    at com.mytreasury.services.backend.AbstractTopicMessageHandler.handle(AbstractTopicMessageHandler.java:47) 
    at com.mytreasury.services.backend.AbstractTopicMessageHandler.handle(AbstractTopicMessageHandler.java:52) 
    at com.mytreasury.services.backend.AbstractTopicMessageHandler.handle(AbstractTopicMessageHandler.java:52) 
    at com.mytreasury.services.backend.AbstractTopicMessageHandler.handle(AbstractTopicMessageHandler.java:52) 
    at com.mytreasury.services.backend.AbstractTopicMessageHandler.handle(AbstractTopicMessageHandler.java:52) 
    at com.mytreasury.services.backend.AbstractTopicMessageHandler.handle(AbstractTopicMessageHandler.java:52) 
    at com.mytreasury.services.backend.AbstractTopicMessageHandler.handle(AbstractTopicMessageHandler.java:52) 
    at com.mytreasury.services.backend.AbstractTopicMessageHandler.handle(AbstractTopicMessageHandler.java:52) 
    at com.mytreasury.services.backend.AbstractTopicMessageHandler.handle(AbstractTopicMessageHandler.java:52) 
    at com.ebs.mytreasury.frontend.message.handler.ResponseGenericMessageHandler.handle(ResponseGenericMessageHandler.java:52) 
    at com.ebs.mytreasury.frontend.socket.EventPublisherSocketHandler.handle(EventPublisherSocketHandler.java:96) 
    at com.ebs.mytreasury.frontend.socket.EventPublisherSocketHandler$1$1.run(EventPublisherSocketHandler.java:135) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: java.io.IOException: Unable to wrap data, invalid status [CLOSED] 
    at org.apache.tomcat.util.net.SecureNioChannel.write(SecureNioChannel.java:647) 
    at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101) 
    at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:157) 
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1241) 
    at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:670) 
    at org.apache.tomcat.util.net.SocketWrapperBase.flushBlocking(SocketWrapperBase.java:607) 
    at org.apache.tomcat.util.net.SocketWrapperBase.flush(SocketWrapperBase.java:597) 
    at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doWrite(WsRemoteEndpointImplServer.java:95) 
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:494) 
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:309) 
    ... 29 common frames omitted 
[https-jsse-nio-8443-exec-3] [FrontendWebSocketHandler] Transport error. Session: StandardWebSocketSession[id=0, uri=/myt/websocket] 
javax.net.ssl.SSLException: bad record MAC 
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) 
    at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1728) 
    at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:981) 
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:907) 
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781) 
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624) 
    at org.apache.tomcat.util.net.SecureNioChannel.read(SecureNioChannel.java:563) 
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1222) 
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1195) 
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1168) 
    at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:62) 
    at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) 
    at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) 
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) 
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:789) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1437) 
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: javax.crypto.BadPaddingException: bad record MAC 
    at sun.security.ssl.EngineInputRecord.decrypt(EngineInputRecord.java:238) 
    at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:974) 
    ... 18 common frames omitted 
[pool-18-thread-3] [FrontendWebSocketHandler] Connection closed. Session: StandardWebSocketSession[id=0, uri=/myt/websocket], CloseStatus: CloseStatus[code=1006, reason=Unable to wrap data, invalid status [CLOSED]]; 
[pool-18-thread-2] [GenericMessageEndpoint] Exception while sending message to the endpoint: java.lang.IllegalStateException: The remote endpoint was in state [TEXT_PARTIAL_WRITING] which is an invalid state for called method, 
[pool-18-thread-1] [GenericMessageEndpoint] Exception while sending message to the endpoint: java.lang.IllegalStateException: The remote endpoint was in state [TEXT_PARTIAL_WRITING] which is an invalid state for called method, 
[pool-18-thread-3] [GenericMessageEndpoint] Exception while sending message to the endpoint: java.io.IOException: java.io.IOException: Unable to wrap data, invalid status [CLOSED], 
संबंधित मुद्दे