The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for called method 已解决

2024-09-03 04:58

本文主要是介绍The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for called method 已解决,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前面有个webSocket自动断开连接的问题,已解决,请见博客:

webSocket java.io.EOFException: null 增加心跳机制解决

然后又报了一个错:

java.lang.IllegalStateException: The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for called methodat org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.checkState(WsRemoteEndpointImplBase.java:1224) ~[tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.textStart(WsRemoteEndpointImplBase.java:1187) ~[tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendString(WsRemoteEndpointImplBase.java:190) ~[tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendText(WsRemoteEndpointBasic.java:37) ~[tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at com.everestfortune.cf.config.webSocket.WebSocketServer.sendMessage(WebSocketServer.java:202) ~[classes!/:0.0.1-SNAPSHOT]at com.everestfortune.cf.config.webSocket.WebSocketServer.onMessage(WebSocketServer.java:155) ~[classes!/:0.0.1-SNAPSHOT]at sun.reflect.GeneratedMethodAccessor176.invoke(Unknown Source) ~[na:na]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_265]at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_265]at org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeBase.onMessage(PojoMessageHandlerWholeBase.java:80) [tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:394) [tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) [tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) [tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) [tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) [tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) [tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) [tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) [tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) [tomcat-embed-websocket-8.5.29.jar!/:8.5.29]at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) [tomcat-embed-core-8.5.29.jar!/:8.5.29]at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) [tomcat-embed-core-8.5.29.jar!/:8.5.29]at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.29.jar!/:8.5.29]at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.29.jar!/:8.5.29]at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.29.jar!/:8.5.29]at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_265]at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_265]at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.29.jar!/:8.5.29]at java.lang.Thread.run(Thread.java:748) [na:1.8.0_265]

 

 websocket推送数据的方法有:

  1. session.getBasicRemote().sendText(message); //同步发送

  2. session.getAsyncRemote().sendText(message); //异步发送

经过测试,在高并发的情况下,两种发送方法都会抛出上面的异常。原因是多个线程同时使用同一session发送的原因。

做如下修改后:

synchronized(session){session.getAsyncRemote().sendText(message);
}

经测试异步发送还是会抛出上述异常,同步不会出现。猜想:异步应该是new一个线程去发送,即使使用synchronized同样会出现两个session同时被不同的线程操作的时机。

决定使用:

synchronized(session){session.getBasicRemote().sendText(message);}

//在网络非常好的情况下。多线程同一个session发送数据

到这里,如果您使用的是单session,问题就应该解决了。

 

webSocket 的Session的定义如下:

/*** 与某个客户端的连接会话,需要通过它来给客户端发送数据*/
private Session session;

如果有多个客户端的话,亦或者同一个用户,或者打开了多个浏览器,开了多个页面

此时Session是不同的。

此时锁住其中一个Session,就不能解决这个问题了。

 

我是用锁住一个全局的静态的对象,来解决多线程同时访问的问题的:

	/*** concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。*/private static final ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();/*** 实现服务器主动推送*/private void sendMessage(String message) throws IOException {// 尝试过锁住方法,还是不行,这里锁住webSocketMap,让多线程,访问不同对象,也能同步synchronized(webSocketMap){JSONObject jsonObject = JSON.parseObject(message);String toUserId = jsonObject.getString("user");if (StringUtils.isNotBlank(toUserId) && webSocketMap.containsKey(toUserId)) {webSocketMap.get(toUserId).getSession().getBasicRemote().sendText(message);}}//this.session.getBasicRemote().sendText(message);}

 

从此,就再也没报过这个问题了

 

补充:

刚开始给方法加synchronized,因为这个方法不是静态的,所以只能锁住当前对象,不能锁住类。

synchronized如果加在了非静态方法上,表示的是synchronized(调用方法的类的对象) {},如果加在了静态方法上,表示的是synchronized(类.class) {}

 

 

 

这篇关于The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for called method 已解决的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1132088

相关文章

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

MySQL 设置AUTO_INCREMENT 无效的问题解决

《MySQL设置AUTO_INCREMENT无效的问题解决》本文主要介绍了MySQL设置AUTO_INCREMENT无效的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录快速设置mysql的auto_increment参数一、修改 AUTO_INCREMENT 的值。

关于跨域无效的问题及解决(java后端方案)

《关于跨域无效的问题及解决(java后端方案)》:本文主要介绍关于跨域无效的问题及解决(java后端方案),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录通用后端跨域方法1、@CrossOrigin 注解2、springboot2.0 实现WebMvcConfig

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

解决JSONField、JsonProperty不生效的问题

《解决JSONField、JsonProperty不生效的问题》:本文主要介绍解决JSONField、JsonProperty不生效的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录jsONField、JsonProperty不生效javascript问题排查总结JSONField

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三

RedisTemplate默认序列化方式显示中文乱码的解决

《RedisTemplate默认序列化方式显示中文乱码的解决》本文主要介绍了SpringDataRedis默认使用JdkSerializationRedisSerializer导致数据乱码,文中通过示... 目录1. 问题原因2. 解决方案3. 配置类示例4. 配置说明5. 使用示例6. 验证存储结果7.

Swagger在java中的运用及常见问题解决

《Swagger在java中的运用及常见问题解决》Swagger插件是一款深受Java开发者喜爱的工具,它在前后端分离的开发模式下发挥着重要作用,:本文主要介绍Swagger在java中的运用及常... 目录前言1. Swagger 的主要功能1.1 交互式 API 文档1.2 客户端 SDK 生成1.3

java连接opcua的常见问题及解决方法

《java连接opcua的常见问题及解决方法》本文将使用EclipseMilo作为示例库,演示如何在Java中使用匿名、用户名密码以及证书加密三种方式连接到OPCUA服务器,若需要使用其他SDK,原理... 目录一、前言二、准备工作三、匿名方式连接3.1 匿名方式简介3.2 示例代码四、用户名密码方式连接4

如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复