让 Jetty Websocket 使用与 JavaScript Websocket 相同的语言
Posted
技术标签:
【中文标题】让 Jetty Websocket 使用与 JavaScript Websocket 相同的语言【英文标题】:Getting Jetty Websocket talking same language as JavaScript Websocket 【发布时间】:2020-04-07 18:17:01 【问题描述】:我编写了一个 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端sn-p:
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... 我读了一些关于 Masked Payloads 的内容,两个客户端都在发送带有 Masking-Keys 的 Masked Payloads,也许与此有关?
知道如何让 Java Jetty 端以类似的方式对数据进行编码吗?甚至 Javascript 端使用的是什么类型的编码?在这一点上我可能想多了......
谢谢!
【问题讨论】:
你确定payload没有被javascript端压缩吗? (例如:permessage-deflate
)来解释为什么你会在 Wireshark 上看到“编码数据”。
看wireshark似乎javascript方面确实在设置Websocket-Extension: premessage-deflate!知道如何在 Jetty 中设置它吗?没有看到任何直接的例子。谢谢!
马上就完美运行了!在 github 上的一个单元测试中找到了一种简单的方法: final ClientUpgradeRequest request = new ClientUpgradeRequest(); request.addExtensions(ExtensionConfig.parse("permessage-deflate"));
【参考方案1】:
正如@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);
...
像魅力一样工作!谢谢!
【讨论】:
以上是关于让 Jetty Websocket 使用与 JavaScript Websocket 相同的语言的主要内容,如果未能解决你的问题,请参考以下文章