英文:
Java WebSocket message limit
问题
我正试图在简单的Java应用程序(使用java.net.http.WebSocket
类)和远程运行的google-chrome
之间创建通信,使用的是google-chrome --remote-debugging-port=9222 --user-data-dir=.
命令。
发送和接收小消息的工作正常,但是在处理较大的消息(16kb)时出现了问题。
以下是Java源代码的一部分:
var uri = new URI("ws://127.0.0.1:9222/devtools/page/C0D7B4DBC53FB39F7A4BE51DA79E96BB");
/// 创建websocket客户端
WebSocket ws = HttpClient
.newHttpClient()
.newWebSocketBuilder()
.connectTimeout(Duration.ofSeconds(30))
.buildAsync(uri, simpleListener)
.join();
// 附加到chrome选项卡的会话ID
String sessionId = "...";
// 发送消息
String message = "{\"id\":1,\"method\":\"Runtime.evaluate\",\"params\":{\"expression\":\"document.body.style.backgroundColor = 'blue';\",\"returnByValue\":true,\"awaitPromise\":true,\"userGesture\":true},\"sessionId\":\"" + sessionId + "\"}";
// 这个可以正常工作
ws.send(message, true);
// 生成包含超过18k个字符的大字符串,用于测试目的
String bigMessage = "{\"id\":2,\"method\":\"Runtime.evaluate\",\"params\":{\"expression\":\"[" + ("1,".repeat(9000)) + "1]\",\"returnByValue\":true,\"awaitPromise\":true,\"userGesture\":true},\"sessionId\":\"" + sessionId + "\"}";
// 这个无法正常工作
ws.send(bigMessage, true);
以下是堆栈信息:
java.net.SocketException: 连接被重置
at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:345)
at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:376)
at java.net.http/jdk.internal.net.http.SocketTube.readAvailable(SocketTube.java:1153)
at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription.read(SocketTube.java:821)
at java.net.http/jdk.internal.net.http.SocketTube$SocketFlowTask.run(SocketTube.java:175)
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
...
我已尝试使用puppeteer
(Node.js库)基本上相同的方法,它可以正常工作。
我在网上找不到关于此问题的任何资源。
在我的示例中是否有什么遗漏之处?
以下是一个简单示例的链接:
https://github.com/zeljic/websocket-devtools-protocol
英文:
I'm trying to create communication between simple Java App (using java.net.http.WebSocket
class) and remote google-chrome
run using google-chrome --remote-debugging-port=9222 --user-data-dir=.
Sending and receiving small messages works as expected, but there is an issue in case of bigger messages, 16kb.
Here is part of java source:
var uri = new URI("ws://127.0.0.1:9222/devtools/page/C0D7B4DBC53FB39F7A4BE51DA79E96BB");
/// create websocket client
WebSocket ws = HttpClient
.newHttpClient()
.newWebSocketBuilder()
.connectTimeout(Duration.ofSeconds(30))
.buildAsync(uri, simpleListener)
.join();
// session Id attached to chrome tab
String sessionId = "...";
// send message
String message = "{\"id\":1,\"method\":\"Runtime.evaluate\",\"params\":{\"expression\":\"document.body.style.backgroundColor = 'blue';\",\"returnByValue\":true,\"awaitPromise\":true,\"userGesture\":true},\"sessionId\":\"" + sessionId + "\"}";
// this works
ws.send(message, true);
// generate big string contains over 18k chars for testing purpose
String bigMessage = "{\"id\":2,\"method\":\"Runtime.evaluate\",\"params\":{\"expression\":\"[" + ("1,".repeat(9000)) + "1]\",\"returnByValue\":true,\"awaitPromise\":true,\"userGesture\":true},\"sessionId\":\"" + sessionId + "\"}";
// this doesn't work
ws.send(bigMessage, true);
Here is stack:
java.net.SocketException: Connection reset
at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:345)
at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:376)
at java.net.http/jdk.internal.net.http.SocketTube.readAvailable(SocketTube.java:1153)
at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription.read(SocketTube.java:821)
at java.net.http/jdk.internal.net.http.SocketTube$SocketFlowTask.run(SocketTube.java:175)
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
...
I've tried basically the same by using puppeteer
(nodejs library) and it works as expected.
I can't find any resource online about this issue.
Is there anything I'm missing in my example?
Here is url to simple example:
https://github.com/zeljic/websocket-devtools-protocol
答案1
得分: 2
根据我目前所见,我最好的猜测是 Chrome Dev Tools 不会处理在那个公开的 webSocketDebuggerUrl
端点上的分段文本消息。Chrome Dev Tools 是否可以配置来处理这些消息是另一个问题。然而,我必须指出,RFC 6455(WebSocket 协议)强制:
> 客户端和服务器必须支持接收分段和非分段消息。
这里有一个解决方法。请记住,这是不受支持的,未来可能会意外更改。在运行客户端时,在命令行上指定以下系统属性 -Djdk.httpclient.websocket.intermediateBufferSize=1048576
(或选择任何其他合适的大小)。只要您在调用 send*
方法时将 boolean last
参数设置为 true
,java.net.http.WebSocket
将会以单个 WebSocket 帧的形式发送未分段的消息。
英文:
Based on what I've seen so far, my best guess would be that Chrome Dev Tools do not process fragmented Text messages on that exposed webSocketDebuggerUrl
endpoint. Whether Chrome Dev Tools can be configured to do so or not, is another question. I must note, however, that RFC 6455 (The WebSocket Protocol) mandates it:
> Clients and servers MUST support receiving both fragmented and unfragmented messages.
There's one workaround I can see here. Keep in mind that this is unsupported and may change in the future unexpectedly. When running your client, specify the following system property on the command line -Djdk.httpclient.websocket.intermediateBufferSize=1048576
(or pick any other suitable size). As long as you keep sending your messages with true
passed as boolean last
argument to the send*
methods, java.net.http.WebSocket
will send messages unfragment, in a single WebSocket frame.
答案2
得分: 0
以下是您要翻译的内容:
在使用 Java 中的 WebSockets 与 Tomcat 服务器发送大型字符串时,我曾遇到类似的问题。
Websocket 服务器可能存在发送或接收的负载限制。
请查看 tomcat 文档 中的 org.apache.tomcat.websocket.textBufferSize。默认情况下,它为 8192 字节,请尝试增加大小。
英文:
Well I had a similar issue when sending a big string by using web-sockets in java with a tomcat server.
There can be payload limit to send or receive in websocket server .
checkout org.apache.tomcat.websocket.textBufferSize in tomcat's doc. By default it is 8192 bytes try increasing the size.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论