9

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

Đorđe Zeljić
  • 1,689
  • 2
  • 13
  • 30
  • Do you have a minimal repo? Also try this format of socket url to see if it helps buffer sizes `websocket://localhost:9222/bar?bufferSize=25000&maxIdleTime=3000&maxTextMessageSize=500&maxBinaryMessageSize=550` – Tarun Lalwani May 07 '20 at 05:42
  • Hm... it would be useful to see the complete source related to WebSocket. Otherwise, it's hard to grasp the picture when what we see is only an approximation (there's no such method as `WebSocket.send(String, boolean)` and all the existing `send*` methods are asynchronous). – pavel May 09 '20 at 18:13
  • 1
    Yes, I'm going to share simple project on github soon. – Đorđe Zeljić May 09 '20 at 18:20
  • https://github.com/zeljic/websocket-devtools-protocol – Đorđe Zeljić May 09 '20 at 19:48
  • It seems that Chrome resets the underlying connection without sending a WebSocket `CLOSE` message. It would be helpful if we could see the logs on the Chrome side. – pavel May 10 '20 at 17:33
  • To show chrome logs add `--enable-logging=stderr --v=1` to chrome run command. – Đorđe Zeljić May 10 '20 at 20:14

2 Answers2

2

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.

Community
  • 1
  • 1
pavel
  • 122
  • 13
  • 1
    This suspicion of mine is somewhat corroborated by this [thread](https://github.com/ChromeDevTools/devtools-protocol/issues/24) on the ChromeDevTools project. – pavel May 11 '20 at 09:50
  • @Đorđe Zeljić have you had a chance to test that workaround? Did it work for you? – pavel May 12 '20 at 18:15
  • I didn't try, but I changed simple example in repo (feature/try-okhttp) to use third-party library and it works on first try. Will try workaround but that is not solution for me. – Đorđe Zeljić May 12 '20 at 19:45
  • Also, I didn't check what okhttp uses `under the hood`, there can be fix for issue with native version too. – Đorđe Zeljić May 12 '20 at 19:47
  • @ĐorđeZeljić would you care to create an issue about this at https://bugs.chromium.org/p/chromium/issues/list? – pavel May 13 '20 at 09:53
  • Chrome is not as issue here IMHO. Because everything works fine in combination with third-party library. But maybe guys on chromium project do know better. – Đorđe Zeljić May 13 '20 at 10:27
  • @ĐorđeZeljić With all due respect, that's a strange argument: "_When feeding a person with diabetes in a normal restaurant with a sugary dessert, they go into comma. That said, I don't think that diabetes is an issue here, as when fed in that other (coincidentally sugar-fee) cafe, everything is fine._" Secondly, it seems like it's a known bug in "Chrome's internal WebSocket server", see https://bugs.chromium.org/p/chromium/issues/detail?id=1069431#c2 (So, **no need to create an issue** against Chromium. It was created some time ago.) – pavel May 13 '20 at 15:06
0

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.