在 tomcat 中无法通过 websocket 发送二进制消息,但在 glassfish 中有效。在 tomcat 中失败并出现 IllegalArgumentException
Unable to send binary message through websocket in tomcat, but works in glassfish. Fails in tomcat with IllegalArgumentException
我正在尝试通过 websocket 发送使用协议缓冲区编码的二进制消息。我能够使用 Glassfish 4.0 成功发送。但是相同的代码在 tomcat 8 中失败,但以下例外。
java.lang.IllegalArgumentException
at java.nio.Buffer.limit(Buffer.java:267)
at org.apache.tomcat.websocket.PerMessageDeflate.sendMessagePart(PerMessageDeflate.java:368)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:297)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:270)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendBytes(WsRemoteEndpointImplBase.java:132)
at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendBinary(WsRemoteEndpointBasic.java:43)
at com.trsim.sim.endpoint.Whiteboard.broadcastSnapshot(Whiteboard.java:164)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeBase.onMessage(PojoMessageHandlerWholeBase.java:80)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageBinary(WsFrameBase.java:586)
at org.apache.tomcat.websocket.WsFrameBase.processDataBinary(WsFrameBase.java:543)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:295)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:130)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:60)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:203)
at org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:194)
at org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:654)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:744)
下面是我的 java 处理二进制消息并将其发回的实现
@OnMessage
public void broadcastSnapshot(ByteBuffer data, Session session) throws IOException {
//I am able to parse the incoming binary header data
Header incomingHeader = Header.parseFrom(data.array());
Header header = Header.newBuilder().setCallback("2").setDecodeusing("MyClasstodecode").build();
//I am able to parse the incoming data
AddressBook incomingAddressBook = AddressBook.parseFrom(data.array());
//Creating Ouput messages
Person john =
Person.newBuilder()
.setId(1234)
.setName("John Doe")
.setEmail("jdoe@example.com")
.addPhone(
Person.PhoneNumber.newBuilder()
.setNumber("555-4321")
.setType(Person.PhoneType.HOME))
.build();
Person keith =
Person.newBuilder().setId(1234).setName("John Doe").setEmail("jdoe@example.com").addPhone(Person.PhoneNumber.newBuilder().setNumber("555-4321").setType(Person.PhoneType.HOME)).build();
AddressBook.Builder addressBook = AddressBook.newBuilder();
addressBook.addPerson(john);
addressBook.addPerson(keith);
//Converting output message to byte array using Protocol buffers
byte[] headerArray = header.toByteArray();
byte[] byteBuffer = addressBook.build().toByteArray();
ByteBuffer outputBuffer = ByteBuffer.allocate(byteBuffer.length + headerArray.length );
outputBuffer.put(headerArray,0,headerArray.length);
outputBuffer.put(byteBuffer,0,byteBuffer.length);
try{
//Send the received message first -- fails in tomcat but works in glassfish 4
ByteBuffer buffer = ByteBuffer.allocate(incomingAddressBook.toByteArray().length).put(incomingAddressBook.toByteArray());
session.getBasicRemote().sendBinary(buffer);
//Send the response -- fails in tomcat.. But works in glassfish 4
session.getBasicRemote().sendBinary(outputBuffer);
}catch(Exception e){
e.printStackTrace();
}
}
看起来您需要检查 tomcat 服务器配置的缓冲区大小。
二进制消息的默认缓冲区大小为 8192 字节。参见 WebSocket Howto
incomingAddressBook.toByteArray().length
的值是多少?
在您的 web.xml.,
中尝试以下操作
<context-param>
<param-name>org.apache.tomcat.websocket.textBufferSize</param-name>
<param-value>32768</param-value>
</context-param>
<context-param>
<param-name>org.apache.tomcat.websocket.binaryBufferSize</param-name>
<param-value>32768</param-value>
</context-param>
此外,请使用以下内容。,
ByteBuffer buffer = ByteBuffer.allocate(incomingAddressBook.toByteArray().length).put(incomingAddressBook.toByteArray());
buffer.flip(); //before sending message
session.getBasicRemote().sendBinary(buffer);
我正在尝试通过 websocket 发送使用协议缓冲区编码的二进制消息。我能够使用 Glassfish 4.0 成功发送。但是相同的代码在 tomcat 8 中失败,但以下例外。
java.lang.IllegalArgumentException
at java.nio.Buffer.limit(Buffer.java:267)
at org.apache.tomcat.websocket.PerMessageDeflate.sendMessagePart(PerMessageDeflate.java:368)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessage(WsRemoteEndpointImplBase.java:297)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.startMessageBlock(WsRemoteEndpointImplBase.java:270)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendBytes(WsRemoteEndpointImplBase.java:132)
at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendBinary(WsRemoteEndpointBasic.java:43)
at com.trsim.sim.endpoint.Whiteboard.broadcastSnapshot(Whiteboard.java:164)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeBase.onMessage(PojoMessageHandlerWholeBase.java:80)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageBinary(WsFrameBase.java:586)
at org.apache.tomcat.websocket.WsFrameBase.processDataBinary(WsFrameBase.java:543)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:295)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:130)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:60)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:203)
at org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:194)
at org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:654)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:744)
下面是我的 java 处理二进制消息并将其发回的实现
@OnMessage
public void broadcastSnapshot(ByteBuffer data, Session session) throws IOException {
//I am able to parse the incoming binary header data
Header incomingHeader = Header.parseFrom(data.array());
Header header = Header.newBuilder().setCallback("2").setDecodeusing("MyClasstodecode").build();
//I am able to parse the incoming data
AddressBook incomingAddressBook = AddressBook.parseFrom(data.array());
//Creating Ouput messages
Person john =
Person.newBuilder()
.setId(1234)
.setName("John Doe")
.setEmail("jdoe@example.com")
.addPhone(
Person.PhoneNumber.newBuilder()
.setNumber("555-4321")
.setType(Person.PhoneType.HOME))
.build();
Person keith =
Person.newBuilder().setId(1234).setName("John Doe").setEmail("jdoe@example.com").addPhone(Person.PhoneNumber.newBuilder().setNumber("555-4321").setType(Person.PhoneType.HOME)).build();
AddressBook.Builder addressBook = AddressBook.newBuilder();
addressBook.addPerson(john);
addressBook.addPerson(keith);
//Converting output message to byte array using Protocol buffers
byte[] headerArray = header.toByteArray();
byte[] byteBuffer = addressBook.build().toByteArray();
ByteBuffer outputBuffer = ByteBuffer.allocate(byteBuffer.length + headerArray.length );
outputBuffer.put(headerArray,0,headerArray.length);
outputBuffer.put(byteBuffer,0,byteBuffer.length);
try{
//Send the received message first -- fails in tomcat but works in glassfish 4
ByteBuffer buffer = ByteBuffer.allocate(incomingAddressBook.toByteArray().length).put(incomingAddressBook.toByteArray());
session.getBasicRemote().sendBinary(buffer);
//Send the response -- fails in tomcat.. But works in glassfish 4
session.getBasicRemote().sendBinary(outputBuffer);
}catch(Exception e){
e.printStackTrace();
}
}
看起来您需要检查 tomcat 服务器配置的缓冲区大小。 二进制消息的默认缓冲区大小为 8192 字节。参见 WebSocket Howto
incomingAddressBook.toByteArray().length
的值是多少?
在您的 web.xml.,
中尝试以下操作<context-param>
<param-name>org.apache.tomcat.websocket.textBufferSize</param-name>
<param-value>32768</param-value>
</context-param>
<context-param>
<param-name>org.apache.tomcat.websocket.binaryBufferSize</param-name>
<param-value>32768</param-value>
</context-param>
此外,请使用以下内容。,
ByteBuffer buffer = ByteBuffer.allocate(incomingAddressBook.toByteArray().length).put(incomingAddressBook.toByteArray());
buffer.flip(); //before sending message
session.getBasicRemote().sendBinary(buffer);