首页 > 解决方案 > 让 Jetty Websocket 使用与 JavaScript Websocket 相同的语言

问题描述

我编写了一个 Jetty Websocket 客户端,它连接到远程服务器并尝试发送 JSON 请求。服务器拒绝请求无效并关闭我的连接。但是,当我使用 Javascript 客户端发送完全相同的 JSON 时,它工作得很好。所以现在我不禁摸不着头脑,是杰克逊 2 对 JSON 与 JSON.stringify() 的编码吗?(差异显示两个 JSON 输出完全相同,没有差异)。Javascript Websockets 和 Jetty 之间的默认配置是否不同?我肯定错过了什么,把头撞在墙上。

Java 端代码段:

final String wsAddress = "ws://" + wssUrl + "/ws";
    final WebSocketClient client = new WebSocketClient();
    final WSEventSocket socket = new WSEventSocket(loginRequest);
    try {
        client.start();

        final ClientUpgradeRequest request = new ClientUpgradeRequest();
        final URI wsUri = new URI(wsAddress);

        logger.info("Connecting to {}", wsUri);
        final Future<Session> session = client.connect(socket, wsUri, request);

        final String requestjson = mapper.writeValueAsString(wsRequestPojo);
        final Future<Void> fut = session.getRemote().sendStringByFuture(requestjson);
...

Javascript侧片段:

var wsRequestJson = {...Use output from Java Side...}
var mySock = new WebSocket("ws://" + wsocketUrl + "/ws");
mySock.onmessage = function(evt) { console.log(evt.data); }; mySock.onclose = function() { console.log("CLOSED"); };
mySock.send(JSON.stringify(wsRequestJson));

Javascript 端运行良好,Java 端没有正确编码数据。我已经尝试过很多东西,比如 JSON 到字节数组,但没有运气。我对这两个事务进行了 Wireshark 处理,我看到了 WebSocket 推送和响应。在 Java 中,我看到一个看起来与 JSON 完全一样的有效负载,而 Wireshark 对其进行了解密。在 Javascript 数据包上,我看到某种类型的编码数据 \214P\311n\3020\024... 我读了一些关于屏蔽有效载荷的信息,两个客户端都在发送带有屏蔽键的屏蔽有效载荷,也许与此有关?

知道如何让 Java Jetty 端以类似的方式对数据进行编码吗?甚至 Javascript 端使用的是什么类型的编码?这个时候我大概想多了……

谢谢!

标签: javascriptjavajsonwebsocketjetty

解决方案


正如@Joakim Erdfelt 在 Javascript 端上方的评论中所述,默认情况下使用 Sec-Websocket-Extension: permessage-deflate。可能不是设置它的最佳方法,但我通过添加以下内容更新了我的 Java 代码:

request.addExtensions(ExtensionConfig.parse("permessage-deflate"));

更新片段:

final String wsAddress = "ws://" + wssUrl + "/ws";
    final WebSocketClient client = new WebSocketClient();
    final WSEventSocket socket = new WSEventSocket(loginRequest);
    try {
        client.start();

        final ClientUpgradeRequest request = new ClientUpgradeRequest();
        request.addExtensions(ExtensionConfig.parse("permessage-deflate"));
        final URI wsUri = new URI(wsAddress);

        logger.info("Connecting to {}", wsUri);
        final Future<Session> session = client.connect(socket, wsUri, request);

        final String requestjson = mapper.writeValueAsString(wsRequestPojo);
        final Future<Void> fut = session.getRemote().sendStringByFuture(requestjson);
...

奇迹般有效!谢谢!


推荐阅读