WebSocket远程端点处于[TEXT_PARTIAL_WRITING]状态

mc *_*c j 12 java spring

我正在使用tomcat 8.0.15,spring 4.1.5.

我实现了3个强制函数来使用websocket,如下所示.这很简单.

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()));
    }
}
Run Code Online (Sandbox Code Playgroud)

某些客户端发送消息,而其他客户端通过handleTextMessage获取消息.

在我的例子中,没有handleTextMessage函数,服务器程序想要向客户端发送文本消息.(为此我将WebSocketSession的Id和用户名保存到map_id中)

String websocketsesssion_id = map_id.get(username);
WebSocketSession wss = map_users.get(websocketsesssion_id);
wss.sendMessage(new TextMessage(new java.util.Date()));
Run Code Online (Sandbox Code Playgroud)

以上代码效果很好.但是当一些客户端的WebSocketSession正在使用并尝试同时使用时,它会产生错误.它意味着1.一些客户端发送消息 - >调用handleTextMessage - >客户端的WebSocketSession正在使用2.服务器程序想要向该客户端发送消息 - >从地图获取客户端的WebSocketSession - >尝试发送消息相同的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)
Run Code Online (Sandbox Code Playgroud)

结果,WebSocketSession关闭,客户端必须再次打开新的WebSocketSession.

所以,我的问题是:

我可以检查WebSocketSession是否正在使用中吗?(在handleTextMessage函数之外)

use*_*515 17

问题是几个线程尝试在套接字上同时写入,所以:

尝试:

String websocketsesssion_id = map_id.get(username);
WebSocketSession wss = map_users.get(websocketsesssion_id);
synchronized(wss) {
 wss.sendMessage(new TextMessage(new java.util.Date()));
}
Run Code Online (Sandbox Code Playgroud)