Java WebSocket The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for called method

Java WebSocket 大约 3254 字

版本

使用了javax.websocketapi

错误信息

java.lang.IllegalStateException: The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for called method
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.checkState(WsRemoteEndpointImplBase.java:1229)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.textStart(WsRemoteEndpointImplBase.java:1191)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendStringByCompletion(WsRemoteEndpointImplBase.java:209)
    at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendStringByFuture(WsRemoteEndpointImplBase.java:197)
    at org.apache.tomcat.websocket.WsRemoteEndpointAsync.sendText(WsRemoteEndpointAsync.java:53)
    at ws.WebSocketServer.onOpen(WebSocketServer.java:57)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.apache.tomcat.websocket.pojo.PojoEndpointBase.doOnOpen(PojoEndpointBase.java:65)
    at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:64)
    at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:133)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:906)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:834)

错误代码

注意:必须是两次一起发送,且第一次使用的Async

session.getAsyncRemote().sendText("123");
session.getAsyncRemote().sendText("456");

//或者

session.getAsyncRemote().sendText("123");
session.getBasicRemote().sendText("456");

原因

因为Async是异步写,调用sendText方法后,随即就执行下面代码,而之后的再次发送调用sendText,原先的state还是TEXT_FULL_WRITING,此时再次校验state就抛出了异常。

// WsRemoteEndpointImplBase.sendString
public void sendString(String text) throws IOException {
    if (text == null) {
        throw new IllegalArgumentException(sm.getString("wsRemoteEndpoint.nullData"));
    }
    stateMachine.textStart();
    sendMessageBlock(CharBuffer.wrap(text), true);
}

// WsRemoteEndpointImplBase$StateMachine.textStart
public synchronized void textStart() {
    checkState(State.OPEN);
    state = State.TEXT_FULL_WRITING;
}

// WsRemoteEndpointImplBase$StateMachine.checkState
private void checkState(State... required) {
    for (State state : required) {
        if (this.state == state) {
            return;
        }
    }
    throw new IllegalStateException(
            sm.getString("wsRemoteEndpoint.wrongState", this.state));
}

解决方法

因避免并发调用Async方法,可考虑使用Basic方法,或放入队列中执行。

参考

https://blogs.oracle.com/pavelbucek/is-websocket-session-really-thread-safe

阅读 383 · 发布于 2021-09-09

————        END        ————

扫描下方二维码关注公众号和小程序↓↓↓

扫描二维码关注我
昵称:
随便看看 换一批