简体   繁体   中英

Java 11 HTTP API WebSocket client throws java.net.SocketException: Connection reset

I'm switching from an undertow WebSocket client, which worked perfectly, to the [built-in implementation available from Java 11]. The connection with the WebSocket is successful, though, after the first message is sent, a SocketException is thrown because of a connection reset. As noted by the documentation, SocketExceptions are usually thrown because of an invalid protocol. Because of this, I tried to switch from TLSv1.3(theoretically the default in Java 11) to TLSv1.2, but this didn't solve the issue either. Here is a simplified version of my code:

    class WebSocketClient implements WebSocket.Listener {
        private void openConnection() {
            var sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(null, null, new SecureRandom());
            HttpClient.newBuilder()
                    .sslContext(sslContext)
                    .build()
                    .newWebSocketBuilder()
                    .header("Origin", "https://web.whatsapp.com")
                    .header("User-Agent", "some user agent")
                    .subprotocols("permessage-deflate", "client_max_window_bits")
                    .connectTimeout(Duration.of(30, ChronoUnit.SECONDS))
                    .buildAsync(URI.create("wss://web.whatsapp.com/ws"), this);
        }

        @Override
        public void onOpen(WebSocket socket) {
            WebSocket.Listener.super.onOpen(socket);
            socket.sendText("tag,irrelevantMessage", true);
        }
    }

I have enabled the debugging feature of the HTTP module and this is the output:

DEBUG: [ForkJoinPool.commonPool-worker-3] [489ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) connectFlows
DEBUG: [ForkJoinPool.commonPool-worker-3] [489ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) ReadSubscriber::onSubscribe
DEBUG: [ForkJoinPool.commonPool-worker-3] [489ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) WritePublisher::subscribe
DEBUG: [ForkJoinPool.commonPool-worker-3] [489ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) WriteSubscription::request 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [494ms] [Transport] write buffer capacity 16384
DEBUG: [ForkJoinPool.commonPool-worker-3] [495ms] [WebSocket] signalOpen
DEBUG: [ForkJoinPool.commonPool-worker-3] [495ms] [WebSocket] enter receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [495ms] [WebSocket] receive state: OPEN
DEBUG: [ForkJoinPool.commonPool-worker-3] [495ms] [WebSocket] enter onOpen 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [495ms] [WebSocket] request 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [502ms] [WebSocket] enter send text 1 payload length=124 last=true
DEBUG: [ForkJoinPool.commonPool-worker-3] [502ms] [Transport] enter send text 1 message.length=124 last=true
DEBUG: [ForkJoinPool.commonPool-worker-3] [502ms] [Transport] enter send task
DEBUG: [ForkJoinPool.commonPool-worker-3] [502ms] [Transport] load message
DEBUG: [ForkJoinPool.commonPool-worker-3] [502ms] [Output] encode text src=[pos=0 lim=124 cap=124] last=true dst=java.nio.HeapByteBuffer[pos=0 lim=16384 cap=16384]
DEBUG: [ForkJoinPool.commonPool-worker-3] [502ms] [Output] put
DEBUG: [ForkJoinPool.commonPool-worker-3] [503ms] [Output] mask
DEBUG: [ForkJoinPool.commonPool-worker-3] [503ms] [Output] moreText
DEBUG: [ForkJoinPool.commonPool-worker-3] [503ms] [Output] frame #0
DEBUG: [ForkJoinPool.commonPool-worker-3] [503ms] [Output] frame opcode=TEXT fin=true len=124
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Output] put
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Output] mask
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Output] moreText
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] enter writing
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] write state: UNREGISTERED
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] registering write event
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) register write event
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] write event
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] registered write event
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] exit writing
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] exit send task
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] enter send task
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] 130 bytes remaining in buffer java.nio.HeapByteBuffer[pos=0 lim=130 cap=16384]
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] enter writing
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] write state: AVAILABLE
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [Transport] writing to the channel
DEBUG: [ForkJoinPool.commonPool-worker-3] [504ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) write: writing 130
DEBUG: [ForkJoinPool.commonPool-worker-3] [505ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) WriteSubscription::request 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [505ms] [Transport] 130 bytes written
DEBUG: [ForkJoinPool.commonPool-worker-3] [505ms] [Transport] finished writing to the channel
DEBUG: [ForkJoinPool.commonPool-worker-3] [505ms] [Transport] exit writing
DEBUG: [ForkJoinPool.commonPool-worker-3] [505ms] [Transport] removeAndComplete error=null
DEBUG: [ForkJoinPool.commonPool-worker-3] [505ms] [Transport] exit send task
DEBUG: [ForkJoinPool.commonPool-worker-3] [506ms] [Transport] exit send text 1 returned jdk.internal.net.http.common.MinimalFuture@5c97152e[Completed normally] (id=63)
DEBUG: [ForkJoinPool.commonPool-worker-3] [506ms] [WebSocket] exit send text 1 returned jdk.internal.net.http.common.MinimalFuture@5c97152e[Completed normally] (id=63)
DEBUG: [ForkJoinPool.commonPool-worker-3] [508ms] [WebSocket] exit onOpen 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [508ms] [WebSocket] change state from OPEN to IDLE true
DEBUG: [ForkJoinPool.commonPool-worker-3] [508ms] [WebSocket] receive state: IDLE
DEBUG: [ForkJoinPool.commonPool-worker-3] [508ms] [WebSocket] change state from IDLE to WAITING true
DEBUG: [ForkJoinPool.commonPool-worker-3] [508ms] [Transport] request 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [508ms] [Transport] enter receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [508ms] [Transport] receive state: UNREGISTERED
DEBUG: [ForkJoinPool.commonPool-worker-3] [508ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) register read event
DEBUG: [ForkJoinPool.commonPool-worker-3] [509ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) readSubscription: requesting 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [509ms] [Transport] exit receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [509ms] [WebSocket] exit receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [509ms] [WebSocket] enter receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [509ms] [WebSocket] receive state: WAITING
DEBUG: [ForkJoinPool.commonPool-worker-3] [509ms] [WebSocket] exit receive task
DEBUG: [HttpClient-1-SelectorManager] [510ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) ReadSubscriber::onError java.net.SocketException: Connection reset
java.net.SocketException: Connection reset
    at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:394)
    at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:426)
    at java.net.http/jdk.internal.net.http.SocketTube.readAvailable(SocketTube.java:1162)
    at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription.read(SocketTube.java:825)
    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)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription.signalReadable(SocketTube.java:766)
    at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$ReadEvent.signalEvent(SocketTube.java:949)
    at java.net.http/jdk.internal.net.http.SocketTube$SocketFlowEvent.handle(SocketTube.java:245)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.handleEvent(HttpClientImpl.java:960)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.lambda$run$3(HttpClientImpl.java:915)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.run(HttpClientImpl.java:915)
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) ReadSubscriber: handling event
DEBUG: [HttpClient-1-SelectorManager] [511ms] [Transport] read event
DEBUG: [HttpClient-1-SelectorManager] [511ms] [Transport] enter receive task
DEBUG: [HttpClient-1-SelectorManager] [511ms] [Transport] receive state: AVAILABLE
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) read
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) read: java.net.SocketException: Connection reset
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) shutdownInput
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] signalError java.net.SocketException: Connection reset
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] enter receive task
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] receive state: ERROR
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] processError
DEBUG: [HttpClient-1-SelectorManager] [511ms] [Transport] closeInput
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] enter onError 2 error=java.net.SocketException: Connection reset
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] exit onError 2
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] signalError java.lang.RuntimeException: An unhandled exception was registered during the lifecycle of this session
DEBUG: [HttpClient-1-SelectorManager] [511ms] [WebSocket] signalError java.lang.RuntimeException: An unhandled exception was registered during the lifecycle of this session
java.lang.RuntimeException: An unhandled exception was registered during the lifecycle of this session
    at whatsapp4j/it.auties.whatsapp4j.whatsapp.WhatsappWebSocket.onError(WhatsappWebSocket.java:212)
    at java.net.http/jdk.internal.net.http.websocket.WebSocketImpl$ReceiveTask.processError(WebSocketImpl.java:500)
    at java.net.http/jdk.internal.net.http.websocket.WebSocketImpl$ReceiveTask.run(WebSocketImpl.java:454)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.websocket.WebSocketImpl.trySetState(WebSocketImpl.java:837)
    at java.net.http/jdk.internal.net.http.websocket.WebSocketImpl.signalError(WebSocketImpl.java:714)
    at java.net.http/jdk.internal.net.http.websocket.WebSocketImpl$SignallingMessageConsumer.onError(WebSocketImpl.java:825)
    at java.net.http/jdk.internal.net.http.websocket.TransportImpl$ReceiveTask.run(TransportImpl.java:704)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.websocket.TransportImpl$ReadEvent.handle(TransportImpl.java:766)
    at java.net.http/jdk.internal.net.http.RawChannelTube$ReadSubscriber.checkEvents(RawChannelTube.java:174)
    at java.net.http/jdk.internal.net.http.RawChannelTube$ReadSubscriber.onError(RawChannelTube.java:212)
    at java.net.http/jdk.internal.net.http.common.SSLTube$DelegateWrapper.onError(SSLTube.java:257)
    at java.net.http/jdk.internal.net.http.common.SSLTube$SSLSubscriberWrapper.complete(SSLTube.java:441)
    at java.net.http/jdk.internal.net.http.common.SSLTube$SSLSubscriberWrapper.onErrorImpl(SSLTube.java:511)
    at java.net.http/jdk.internal.net.http.common.SSLTube$SSLSubscriberWrapper.onError(SSLTube.java:525)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper$DownstreamPusher.run1(SubscriberWrapper.java:294)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper$DownstreamPusher.run(SubscriberWrapper.java:259)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper.errorCommon(SubscriberWrapper.java:419)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.errorCommon(SSLFlowDelegate.java:366)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper.onError(SubscriberWrapper.java:410)
    at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$ReadSubscription.signalCompletion(SocketTube.java:629)
    at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription.read(SocketTube.java:813)
    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)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription.signalReadable(SocketTube.java:766)
    at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$ReadEvent.signalEvent(SocketTube.java:949)
    at java.net.http/jdk.internal.net.http.SocketTube$SocketFlowEvent.handle(SocketTube.java:245)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.handleEvent(HttpClientImpl.java:960)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.lambda$run$3(HttpClientImpl.java:915)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.run(HttpClientImpl.java:915)
Caused by: java.net.SocketException: Connection reset
    at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:394)
    at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:426)
    at java.net.http/jdk.internal.net.http.SocketTube.readAvailable(SocketTube.java:1162)
    at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription.read(SocketTube.java:825)
    ... 11 more
DEBUG: [HttpClient-1-SelectorManager] [512ms] [WebSocket] exit receive task
DEBUG: [HttpClient-1-SelectorManager] [512ms] [WebSocket] set state ERROR (previous WAITING) true
DEBUG: [HttpClient-1-SelectorManager] [512ms] [WebSocket] close
DEBUG: [HttpClient-1-SelectorManager] [512ms] [Transport] closeInput
DEBUG: [HttpClient-1-SelectorManager] [512ms] [Transport] closeOutput
DEBUG: [HttpClient-1-SelectorManager] [512ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) shutdownOutput
DEBUG: [HttpClient-1-SelectorManager] [512ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) close
DEBUG: [HttpClient-1-SelectorManager] [512ms] [Transport] enter send task
DEBUG: [HttpClient-1-SelectorManager] [512ms] [Transport] exit send task
DEBUG: [HttpClient-1-SelectorManager] [512ms] [Transport] exit receive task
DEBUG: [HttpClient-1-SelectorManager] [512ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) WriteSubscription::cancel

Update:

As suggested in the comments, I've modified my code and now the exception's message is "Connection reset by peer" instead of "Connection reset". These are the new logs:

DEBUG: [ForkJoinPool.commonPool-worker-3] [333ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) connectFlows
DEBUG: [ForkJoinPool.commonPool-worker-3] [333ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) ReadSubscriber::onSubscribe
DEBUG: [ForkJoinPool.commonPool-worker-3] [333ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) WritePublisher::subscribe
DEBUG: [ForkJoinPool.commonPool-worker-3] [333ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) WriteSubscription::request 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [336ms] [Transport] write buffer capacity 16384
DEBUG: [ForkJoinPool.commonPool-worker-3] [337ms] [WebSocket] signalOpen
DEBUG: [ForkJoinPool.commonPool-worker-3] [337ms] [WebSocket] enter receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [337ms] [WebSocket] receive state: OPEN
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] enter onOpen 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] request 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] exit onOpen 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] change state from OPEN to IDLE true
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] receive state: IDLE
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] change state from IDLE to WAITING true
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [Transport] request 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [Transport] enter receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [Transport] receive state: UNREGISTERED
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) register read event
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) readSubscription: requesting 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [Transport] exit receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] exit receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] enter receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] receive state: WAITING
DEBUG: [ForkJoinPool.commonPool-worker-3] [338ms] [WebSocket] exit receive task
DEBUG: [ForkJoinPool.commonPool-worker-3] [339ms] [WebSocket] enter send binary 1 payload=java.nio.HeapByteBuffer[pos=0 lim=0 cap=0] last=true
DEBUG: [ForkJoinPool.commonPool-worker-3] [339ms] [Transport] enter send binary 1 message.remaining=0 last=true
DEBUG: [ForkJoinPool.commonPool-worker-3] [339ms] [Transport] enter send task
DEBUG: [ForkJoinPool.commonPool-worker-3] [339ms] [Transport] load message
DEBUG: [ForkJoinPool.commonPool-worker-3] [339ms] [Output] encode binary src=java.nio.HeapByteBuffer[pos=0 lim=0 cap=0] last=true dst=java.nio.HeapByteBuffer[pos=0 lim=16384 cap=16384]
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Output] frame opcode=BINARY fin=true len=0
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] enter writing
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] write state: UNREGISTERED
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] registering write event
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) register write event
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] write event
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] registered write event
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] exit writing
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] exit send task
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] enter send task
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] 6 bytes remaining in buffer java.nio.HeapByteBuffer[pos=0 lim=6 cap=16384]
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] enter writing
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] write state: AVAILABLE
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [Transport] writing to the channel
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) write: writing 6
DEBUG: [ForkJoinPool.commonPool-worker-3] [340ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) WriteSubscription::request 1
DEBUG: [ForkJoinPool.commonPool-worker-3] [341ms] [Transport] 6 bytes written
DEBUG: [ForkJoinPool.commonPool-worker-3] [341ms] [Transport] finished writing to the channel
DEBUG: [ForkJoinPool.commonPool-worker-3] [341ms] [Transport] exit writing
DEBUG: [ForkJoinPool.commonPool-worker-3] [341ms] [Transport] removeAndComplete error=null
DEBUG: [ForkJoinPool.commonPool-worker-3] [341ms] [Transport] exit send task
DEBUG: [ForkJoinPool.commonPool-worker-3] [342ms] [Transport] exit send binary 1 returned jdk.internal.net.http.common.MinimalFuture@2750fa5d[Completed normally] (id=64)
DEBUG: [ForkJoinPool.commonPool-worker-3] [342ms] [WebSocket] exit send binary 1 returned jdk.internal.net.http.common.MinimalFuture@2750fa5d[Completed normally] (id=64)
DEBUG: [HttpClient-1-Worker-0] [344ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) WriteSubscription::cancel
DEBUG: [HttpClient-1-Worker-0] [344ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) shutdownOutput
DEBUG: [HttpClient-1-Worker-0] [345ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) ReadSubscriber::onError java.io.IOException: Connection reset by peer
java.io.IOException: Connection reset by peer
    at java.base/sun.nio.ch.SocketDispatcher.writev0(Native Method)
    at java.base/sun.nio.ch.SocketDispatcher.writev(SocketDispatcher.java:58)
    at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:182)
    at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:130)
    at java.base/sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:563)
    at java.base/java.nio.channels.SocketChannel.write(SocketChannel.java:642)
    at java.net.http/jdk.internal.net.http.SocketTube.writeAvailable(SocketTube.java:1228)
    at java.net.http/jdk.internal.net.http.SocketTube$InternalWriteSubscriber.tryFlushCurrent(SocketTube.java:342)
    at java.net.http/jdk.internal.net.http.SocketTube$InternalWriteSubscriber.onNext(SocketTube.java:309)
    at java.net.http/jdk.internal.net.http.SocketTube.onNext(SocketTube.java:133)
    at java.net.http/jdk.internal.net.http.SocketTube.onNext(SocketTube.java:56)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper$DownstreamPusher.run1(SubscriberWrapper.java:316)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper$DownstreamPusher.run(SubscriberWrapper.java:259)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper.outgoing(SubscriberWrapper.java:232)
    at java.net.http/jdk.internal.net.http.common.SubscriberWrapper.outgoing(SubscriberWrapper.java:198)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Writer.sendResultBytes(SSLFlowDelegate.java:934)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Writer.processData(SSLFlowDelegate.java:817)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Writer$WriterDownstreamPusher.run(SSLFlowDelegate.java:694)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:271)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:224)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Writer.triggerWrite(SSLFlowDelegate.java:771)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate.doHandshake(SSLFlowDelegate.java:1083)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate.doClosure(SSLFlowDelegate.java:1169)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.unwrapBuffer(SSLFlowDelegate.java:549)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(SSLFlowDelegate.java:433)
    at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run(SSLFlowDelegate.java:268)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(SequentialScheduler.java:175)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:147)
    at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:198)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:831)
DEBUG: [HttpClient-1-Worker-0] [345ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) ReadSubscriber: handling event
DEBUG: [HttpClient-1-Worker-0] [345ms] [Transport] read event
DEBUG: [HttpClient-1-Worker-0] [345ms] [Transport] enter receive task
DEBUG: [HttpClient-1-Worker-0] [345ms] [Transport] receive state: AVAILABLE
DEBUG: [HttpClient-1-Worker-0] [345ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) read
DEBUG: [HttpClient-1-Worker-0] [345ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) read: java.io.IOException: Connection reset by peer
DEBUG: [HttpClient-1-Worker-0] [345ms] [WebSocket] RawChannelTube(SSLTube(SocketTube(1))) shutdownInput
DEBUG: [HttpClient-1-Worker-0] [346ms] [WebSocket] signalError java.io.IOException: Connection reset by peer
DEBUG: [HttpClient-1-Worker-0] [346ms] [WebSocket] enter receive task
DEBUG: [HttpClient-1-Worker-0] [346ms] [WebSocket] receive state: ERROR
DEBUG: [HttpClient-1-Worker-0] [346ms] [WebSocket] processError
DEBUG: [HttpClient-1-Worker-0] [346ms] [Transport] closeInput
DEBUG: [HttpClient-1-Worker-0] [346ms] [WebSocket] enter onError 2 error=java.io.IOException: Connection reset by peer
DEBUG: [HttpClient-1-Worker-0] [346ms] [WebSocket] exit onError 2

I've also reproduced the same piece of code using JakartaEE 9.1 and it seems to work perfectly

@ClientEndpoint(configurator = ClientTest.class)
public class ClientTest extends ClientEndpointConfig.Configurator {
    public void openConnection() throws DeploymentException, IOException {
        var session = createSession();
        session.getBasicRemote().sendText("tag,irrelevantMessage");
    }

    private Session createSession() throws DeploymentException, IOException {
        return ContainerProvider.getWebSocketContainer().connectToServer(this, URI.create("wss://web.whatsapp.com/ws"));
    }

    @OnMessage
    public void onTextMessage(String message){
        System.out.println(message);
    }

    @Override
    public void beforeRequest(Map<String, List<String>> headers) {
        headers.put("Origin", List.of("https://web.whatsapp.com"));
    }
}

Even sending an empty binary message will throw an equivalent exception

Please try without the timeout parameter .connectTimeout(Duration.of(30, ChronoUnit.SECONDS)) ...

class WebSocketClient implements WebSocket.Listener {
    private void openConnection() {
        var sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(null, null, new SecureRandom());
        HttpClient.newBuilder()
                .sslContext(sslContext)
                .build()
                .newWebSocketBuilder()
                .header("Origin", "https://web.whatsapp.com")
                .header("User-Agent", "some user agent")
                .subprotocols("permessage-deflate", "client_max_window_bits")
                .buildAsync(URI.create("wss://web.whatsapp.com/ws"), this);
    }

    @Override
    public void onOpen(WebSocket socket) {
        WebSocket.Listener.super.onOpen(socket);
        socket.sendText("tag,irrelevantMessage", true);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM