我在嘗試從Spring Websocket服務器發送數據(託管在Tomcat上)時似乎在嘗試發送消息的過程中重置連接。當發送大量的二進制數據時(這裏的示例中的字節數爲5526584字節),錯誤似乎會發生得更多,但我已經看到它發生在文本通道上,並且數據量也較少。然而,發送更多5個左右的MB似乎使其相對一致地崩潰。Spring Websocket服務器在發送大量數據時重置連接
編輯 - 下面的結束編輯塊是服務器端的代碼和錯誤。我現在認爲錯誤是由服務器端造成的。我輸入了一些時間戳,看起來客戶端在服務器拋出錯誤之前收到onClose錯誤。關閉的原因是緩衝區溢出。下面是代碼,我設置WebSocket的容器,並啓動會話:
WebSocketContainer c = ContainerProvider.getWebSocketContainer();
c.setDefaultMaxTextMessageBufferSize(128000000); // Should we enable these on the client?
c.setDefaultMaxBinaryMessageBufferSize(128000000); // Should we enable these on the client?
c.setDefaultMaxSessionIdleTimeout(500000);
c.setAsyncSendTimeout(50000);
session = c.connectToServer(this, config, new URI("wss://" + SERVER + ":" + PORT + WEBSOCKETENDPOINT));
後來我打印出會議MaxBuffer大小,他們都被設置爲1.28預期。
末編輯
這裏是堆棧跟蹤:
java.io.IOException: An established connection was aborted by the software in your host machine
at sun.nio.ch.SocketDispatcher.write0(Native Method)
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
at org.apache.tomcat.util.net.SecureNioChannel.flush(SecureNioChannel.java:143)
at org.apache.tomcat.util.net.SecureNioChannel.close(SecureNioChannel.java:494)
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.close(NioEndpoint.java:1201)
at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.doClose(WsRemoteEndpointImplServer.java:167)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.close(WsRemoteEndpointImplBase.java:710)
at org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:599)
at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:480)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:313)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:258)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendPartialBytes(WsRemoteEndpointImplBase.java:161)
at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendBinary(WsRemoteEndpointBasic.java:56)
at org.springframework.web.socket.adapter.standard.StandardWebSocketSession.sendBinaryMessage(StandardWebSocketSession.java:202)
at org.springframework.web.socket.adapter.AbstractWebSocketSession.sendMessage(AbstractWebSocketSession.java:107)
at org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator.tryFlushMessageBuffer(ConcurrentWebSocketSessionDecorator.java:132)
at org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator.sendMessage(ConcurrentWebSocketSessionDecorator.java:104)
at myHandlerpart2.handleBinaryMessage(myHandlerpart2.java:252)
at myHandler.handleMessageFromClient(myHandler.java:200)
at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:307)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56)
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleBinaryMessage(StandardWebSocketHandlerAdapter.java:120)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$100(StandardWebSocketHandlerAdapter.java:42)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$4.onMessage(StandardWebSocketHandlerAdapter.java:87)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$4.onMessage(StandardWebSocketHandlerAdapter.java:84)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageBinary(WsFrameBase.java:576)
at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageBinary(WsFrameServer.java:122)
at org.apache.tomcat.websocket.WsFrameBase.processDataBinary(WsFrameBase.java:535)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:127)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:73)
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:861)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
在我的WebSocket配置者我設置非常寬鬆的緩衝區和超時
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new
ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(128000000); //128 MB
container.setMaxBinaryMessageBufferSize(128000000); //128 MB
container.setMaxSessionIdleTimeout(500000);
container.setAsyncSendTimeout(50000);
return container;
}
我還設置了限制SubProtoclHandler
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
SubProtocolWebSocketHandler test = new SubProtocolWebSocketHandler(new DirectChannel(), clientInboundChannel());
test.setSendBufferSizeLimit(128000000);
test.setSendTimeLimit(50000);
for(SubProtocolHandler handler : handlers)
{
test.addProtocolHandler(handler);
}
MyWebSocketHandshakeHandler handshaker = new MyWebSocketHandshakeHandler();
handshaker.setSupportedProtocols(test.getSubProtocols().toArray(new String[0]));
registry.addHandler(test, websocketEndpoint).setHandshakeHandler(handshaker)
.addInterceptors(new HttpSessionHandshakeInterceptor()).setAllowedOrigins("*");
}
最後導致該錯誤的實際發送看起來像這樣
byte[] tbuf = null;
try {
tbuf = jsonMapper.writeValueAsBytes(demoLists.get(stage));
ByteBuffer buf = ByteBuffer.allocate(tbuf.length);
buf.put(tbuf);
buf.flip();
WebSocketMessage<ByteBuffer> ret = new BinaryMessage(buf);
System.out.println("Binary limit: " + session.getBinaryMessageSizeLimit());
System.out.println("Sending bytes: " + ret.getPayloadLength());
if(session.isOpen()) {
session.sendMessage(ret);
} else {
System.out.println("Session is closed already.");
}
有很多代碼運動件,所以讓我知道如果你需要的任何其他信息。