我正在使用tomcat 8.0.23来终止我的websocket连接。 我有以下代码来处理传入的消息:
@OnMessage
public void onMsg(Session session, byte[] request) {
executorService.execute(() ->
session.getAsyncRemote().sendBinary(
ByteBuffer.wrap(getResponse(session, request)), result -> {
if (!result.isOK()) {
LOGGER.catching(result.getException());
}
}
));
}
但我得到以下例外:
Exception in thread "pool-6-thread-10160" java.lang.IllegalStateException: The remote endpoint was in state [BINARY_FULL_WRITING] which is an invalid state for called method
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.checkState(WsRemoteEndpointImplBase.java:1148)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.binaryStart(WsRemoteEndpointImplBase.java:1101)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendBytesByCompletion(WsRemoteEndpointImplBase.java:152)
at org.apache.tomcat.websocket.WsRemoteEndpointAsync.sendBinary(WsRemoteEndpointAsync.java:65)
看起来当我尝试同时写入同一个会话时,tomcat会抛出异常。
错误来自this method:
private void checkState(State... required) {
for (State state : required) {
if (this.state == state) {
return;
}
}
throw new IllegalStateException(
sm.getString("wsRemoteEndpoint.wrongState", this.state));
}
我没想到sendBinary抛出异常,因为基于java doc:
sendBinary void sendBinary(ByteBuffer data,SendHandler handler)
抛出:IllegalArgumentException - 如果数据或处理程序为null。
所以看起来tomcat实现会检查this code中状态是否为open
:
public synchronized void binaryStart() {
checkState(State.OPEN);
state = State.BINARY_FULL_WRITING;
}
如果它不是open
那么它将抛出该异常。
值得注意的是,在RemoteEndpoint.Basic
下RemoteEndpoint.Async
(不是RemoteEndpoint.Async
),我们读到:
如果此RemoteEndpoint下面的websocket连接正忙 例如,在发出呼叫以发送另一个消息时发送消息 如果两个线程同时尝试调用send方法,或者如果一个 开发人员尝试在中间发送新消息 发送一个现有的,连接时调用的send方法 已经忙碌可能会抛出IllegalStateException。
RemoteEndpoint.Async.sendBinary
没有这样的段落!
现在的问题
在其他人写入同一会话时,是否无法在会话中调用> library(rgdal)
Loading required package: sp
rgdal: version: 1.0-7, (SVN revision 559)
Geospatial Data Abstraction Library extensions to R successfully loaded
Loaded GDAL runtime: GDAL 1.11.1, released 2014/09/24
Path to GDAL shared files: /usr/local/share/gdal
Loaded PROJ.4 runtime: Rel. 4.9.1, 04 March 2015, [PJ_VERSION: 491]
Path to PROJ.4 shared files: (autodetected)
WARNING: no proj_defs.dat in PROJ.4 shared files
Linking to sp version: 1.2-1
?
如果不可接受,在尝试写入之前如何检查远程端点的状态!
更新1:
看起来java.net上有同样问题的java doc。
更新2:
链接到apache bugzilla上的类似discussion。
答案 0 :(得分:1)
我遇到了同样的情况。该文件很糟糕。我就是这样处理的。
实际上,我编写了一个actor来包装socketSession。调用send方法时会产生一个事件。每个actor都将在Looper中注册,其中包含工作线程和事件队列。同时工作线程不断发送消息。
因此,我将在内部使用sync-send方法,actor模型将确保并发性。
现在的关键问题是关于Looper的数量。你知道,你不能做太多或太少的线程。但您仍然可以根据业务案例估算一个数字,并继续进行调整。