【问题标题】:Require assistance with simple pure Java 11 WebSocket client example需要简单的纯 Java 11 WebSocket 客户端示例的帮助
【发布时间】:2019-08-18 05:35:54
【问题描述】:

网络上似乎很少有 Java 11(纯 Java 非基于框架的)WebSocket 客户端代码示例,所以我希望 StackOverflow 可以再次为我提供帮助。

This 是我找到的最接近的,但不幸的是,在我的(新手)眼中,它似乎不是展示如何使用来自 WebSocket 侦听器的数据的完整解决方案。

查看WebSocket.Listener implementation, the onText 回调方法,我认为可以提供我需要的东西,但我正在努力弄清楚如何从套接字返回 CompletionStage 对象和某种字符串数据。

这是我目前的一些测试代码。

不胜感激。谢谢

    public class Main {

        public static void main(String[] args) {

           WebSocketClient wsc = new WebSocketClient();
           wsc.startSocket("ws://demos.kaazing.com/echo");

           int i = 0;   

           // Bad, very bad
           do {} while (i == 0);
        }
    }


    public class WebSocketClient implements WebSocket.Listener {

        @Override
        public void onOpen(WebSocket webSocket) {
           //...
            System.out.println("Go...Open".concat(
                    webSocket.getSubprotocol()));
        }

        @Override
        public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
           //...
            System.out.println(data.toString());

            // How do I return the CompletionStage object
            // return CompletionStage<String>
        }

        @Override
        public void onError(WebSocket webSocket, Throwable error) {
           //..
            System.out.println("Bad day! ".concat(webSocket.toString()));
        }

        void startSocket(String connection) {
            CompletableFuture<WebSocket> server_cf = HttpClient.
                    newHttpClient().
                    newWebSocketBuilder().
                    buildAsync(URI.create(connection),
                            new WebSocketClient());
            WebSocket server = server_cf.join();
            server.sendText("Hello!", true);
        }
    }

【问题讨论】:

  • 不是很担心(因为我只是想要一些帮助),但如果你要投反对票,如果你至少能说出哪里出了问题,那就太好了。
  • 你知道为什么CompletionStage需要从on返回-Listener的方法吗?换句话说,这些阶段的作用是什么?

标签: websocket java-11 java-http-client


【解决方案1】:

管理返回 CompletionStage 的 WebSocket 响应的模式是:

@Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
    // return inmmediately but response is geenrated lazyly.
    return CompletableFuture.supplyAsync(() -> {
        String response = "Received  ...";
        // do slow task. Access to database or access to a server.
        return response;
    });
}

仅在快速生成响应时才建议使用这种简单的实现方式。

@Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
    // fast response.
    String response = "The text has " + data.length() + " chars";
    return CompletableFuture.completedFuture(response);
}

【讨论】:

    【解决方案2】:

    您可以在下面找到一个工作示例。我对上面的代码做了一些修改:

    • onOpen 需要在 websocket 上调用 request(1)(调用默认实现)才能接收进一步的调用。
    • 将方法startSocket移动到主方法中
    • 用倒计时锁代替忙等待
    • 将类WebSocketClient 声明为(静态)内部类

    但除了这些(外观)更改之外,程序会遵循您的想法,即首先构建一个 websocket 连接,然后在成功构建后将文本 Hello! 发送到 echo 服务器。这也可以直接在方法onOpen 中完成。

        import java.net.URI;
        import java.net.http.HttpClient;
        import java.net.http.WebSocket;
        import java.util.concurrent.CompletionStage;
        import java.util.concurrent.CountDownLatch;
    
        public class Main {
    
            public static void main(String[] args) throws Exception {
                CountDownLatch latch = new CountDownLatch(1);
    
                WebSocket ws = HttpClient
                        .newHttpClient()
                        .newWebSocketBuilder()
                        .buildAsync(URI.create("ws://demos.kaazing.com/echo"), new WebSocketClient(latch))
                        .join();
                ws.sendText("Hello!", true);
                latch.await();
            }
    
            private static class WebSocketClient implements WebSocket.Listener {
                private final CountDownLatch latch;
    
                public WebSocketClient(CountDownLatch latch) { this.latch = latch; }
    
                @Override
                public void onOpen(WebSocket webSocket) {
                    System.out.println("onOpen using subprotocol " + webSocket.getSubprotocol());
                    WebSocket.Listener.super.onOpen(webSocket);
                }
    
                @Override
                public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
                    System.out.println("onText received " + data);
                    latch.countDown();
                    return WebSocket.Listener.super.onText(webSocket, data, last);
                }
    
                @Override
                public void onError(WebSocket webSocket, Throwable error) {
                    System.out.println("Bad day! " + webSocket.toString());
                    WebSocket.Listener.super.onError(webSocket, error);
                }
            }
        }
    

    顺便说一句,没有协商 supprotocol,因此方法 webSocket.getSubprotocol() 返回一个空字符串。控制台中的输出是

        onOpen using subprotocol 
        onText received Hello!
    

    【讨论】:

    • 您不需要虔诚地调用WebSocket.Listener.super.onXXX 方法。这一切都取决于您的需求。特别是,onError 指定:@implSpec The default implementation does nothing
    • @pavel,你是对的,谢谢你的评论。所有的超级调用都可以被丢弃(并且onText 可以返回null),但是在方法onOpen 中必须执行语句webSocket.request(1) 以使websocket 能够调用至少一个接收方法(原始示例中缺少此方法)。
    • 嗨,如果我想将身份验证数据发送到 websocket 服务器以进行连接,我们该怎么做。我能够成功地使用 JavaScript 建立 Web 套接字连接。下面是我发送到 WS 连接的 JSON 对象 => jsonSendObj = { "channel":"", "task":"cn", "acctid":UID, "user":UID, "token": userSessionID };我们如何使用 Java 发送它?我们可以使用相同的 SetString 方法吗?
    猜你喜欢
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    相关资源
    最近更新 更多