【问题标题】:Tyrus websocket client @OnMessage never called - Storj Open source projectTyrus websocket 客户端 @OnMessage 从未调用过 - Storj 开源项目
【发布时间】:2017-01-02 09:39:31
【问题描述】:

我正在开发一个开源项目,Storj。我正在编写一个连接到 Node.js websocket 后端的 Java 客户端。客户使用 Tyrus。沟通应该如下:

  • 连接
  • 客户端发送身份验证令牌(文本)。
  • 服务器发回一个文件(二进制)。
  • 服务器关闭连接。

我遇到了问题,因为我的 @OnMessage 永远不会被调用。我已经尝试使用一个简单的 javascript 客户端在线访问相同的 URL 和相同的令牌: https://www.websocket.org/echo.html

我确实收到了使用这个的响应,它告诉我 Java 项目有问题。

在能够下载文件之前,在较早的阶段,我可以毫无问题地上传文件。 但是,该步骤不需要调用@OnMessage(它只是上传文件,然后服务器会断开一条消息),所以我不确定我的@OnMessage 是否正常工作。

这里是 Websocket 的相关代码(也可以在 Github 上找到): https://github.com/NutterzUK/storj-java-bridge-client/blob/master/storj-client/src/main/java/storj/io/client/websockets/WebsocketFileRetriever.java

package storj.io.client.websockets;

import com.google.gson.Gson;
import storj.io.restclient.model.FilePointer;

import javax.websocket.*;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;

import java.util.concurrent.CountDownLatch;
import java.util.logging.Logger;

/**
 * Created by steve on 12/07/2016.
 */
@ClientEndpoint
public class WebsocketFileRetriever {

    private Logger logger = Logger.getLogger(this.getClass().getName());
    private Gson gson = new Gson();
    private FilePointer filePointer;
    private File outputFile;
    private AuthorizationModel authModel;
    private CountDownLatch latch;

    public WebsocketFileRetriever(FilePointer filePointer, File outputFile, CountDownLatch latch){
        this.filePointer = filePointer;
        this.latch = latch;
        this.outputFile = outputFile;
        authModel = new AuthorizationModel();
        authModel.setToken(filePointer.getToken());
        authModel.setOperation(filePointer.getOperation());
        authModel.setHash(filePointer.getHash());
    }

    @OnMessage
    public void onMessage(String s){
        logger.info("Received ... " + s);
    }

    @OnMessage
    public void onMessage(ByteBuffer message, Session session) {
        logger.info("Received ...." + message);
    }

    @OnOpen
    public void onOpen(Session session, EndpointConfig endpointConfig) {
        logger.info("Opened");
        try {
            session.getBasicRemote().sendText(gson.toJson(authModel), true);
        } catch (IOException e) {
            e.printStackTrace();
        }

        logger.info("sent: " + gson.toJson(authModel));
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        logger.info("Closed Websocket: " + closeReason.getCloseCode() + " " + closeReason.getReasonPhrase());
        //latch.countDown();
    }

    @OnError
    public void onError(Session session, Throwable t) {
        t.printStackTrace();
    }
}

以及启动此 websocket 的代码,可在此处获得 https://github.com/NutterzUK/storj-java-bridge-client/blob/master/storj-client/src/main/java/storj/io/client/DefaultStorjClient.java

        CountDownLatch latch;
        latch = new CountDownLatch(1);
        ClientManager wsClient = ClientManager.createClient();
        try {
            wsClient.setDefaultMaxBinaryMessageBufferSize(Integer.MAX_VALUE);
            wsClient.setDefaultMaxTextMessageBufferSize(Integer.MAX_VALUE);
            logger.info("CONNECTING TO: " + "ws://" + pointer.getFarmer().getAddress() + ":" + pointer.getFarmer().getPort());
            final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();

            wsClient.connectToServer(new WebsocketFileRetriever(pointer, encryptedOutputFile, latch), cec, new URI("ws://" + pointer.getFarmer().getAddress() + ":" + pointer.getFarmer().getPort()));
            latch.await();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

我也尝试将 Tyrus 升级到最新版本,我得到了相同的结果。有什么想法吗?

这段代码的输出是:

    Aug 25, 2016 8:55:31 PM storj.io.client.DefaultStorjClient downloadFile
INFO: CONNECTING TO: ws://164.storj.eu:8607
Aug 25, 2016 8:55:35 PM storj.io.client.websockets.WebsocketFileRetriever onOpen
INFO: Opened
Aug 25, 2016 8:55:35 PM storj.io.client.websockets.WebsocketFileRetriever onOpen
INFO: sent: {"token":"06c36d4bac4f07ee1751068b5b2230f22e884b38","hash":"837b79bec927a1d8fa7fedd2ea0bb276e0d86e0f","operation":"PULL"}
Aug 25, 2016 8:56:11 PM storj.io.client.websockets.WebsocketFileRetriever onClose
INFO: Closed Websocket: NORMAL_CLOSURE Closing

发送消息后,它会在@OnClose 发出“NORMAL_CLOSURE”消息之前挂起一段时间。

更新:运行它以重现问题的一种非常简单的方法

我已经在 git 仓库中添加了测试用户名和密码,所以可用的代码在这里:https://github.com/NutterzUK/storj-java-bridge-client

要运行它,你只需要运行 storj.io.client.main.MainTest

快速浏览它的功能。它首先会发送一些 HTTP 请求以获取令牌。它将使用该令牌通过 websocket 连接到某人的机器,并将该令牌作为文本发送。作为响应,它应该以字节形式接收文件。

在连接之前,它会打印出令牌和即将连接的地址。它会在关闭之前挂起一段时间,并且不会调用任何 onMessage 方法。对于测试,如果您将 System.exit 放在那里(取消注释 DefaultStorjClient.java 中的第 152 行),它将无法连接,因此您可以在另一个客户端中使用该令牌。我已经使用https://www.websocket.org/echo.html 进行了测试(确保您的浏览器将允许不安全的 URL,因为它不是“wss”,要在 Chrome 中执行此操作,您需要单击右上角的盾牌。我可以看到服务器确实响应:

这表明确实发送了一个 blob 作为对文本消息的响应,但 Tyrus 中的 @OnMessage 从未被触发。

【问题讨论】:

  • JS 服务器将此作为“blob”发送,这可能是相关/或问题吗?
  • 有一些可测试的东西会很好。我的意思是.. 我连接到该服务,但我无法让它向我发送文件,所以我无法测试 Tyrus 是否可以从您的服务器接收消息。无论如何,Tyrus 也可以与 echo 服务器一起使用,所以这并不是一个真正有用的测试。 (只需将您的 tyrus 客户端指向“ws://echo.websocket.org”并发送消息)。
  • 谢谢。是的,它确实适用于回声服务器,但我认为回声服务器不会发回字节。我想如果你在 storj.io 上注册一个帐户(它是免费的),你可以运行“testmain”并发送一个文件来测试它。这一切都在 github 上,不幸的是,我真的很困惑为什么会这样,所以我将在 7 小时内尽可能地为这个问题添加赏金。
  • 我实际上可以创建一个我认为的测试帐户,并且可以在此处提供用户名/密码以节省其他人这样做。我会这样做并将其添加到问题中,我还将更新 TestMain 以仅下载单个文件以突出显示问题。
  • 我在描述中添加了“更新:运行此程序以查看问题的一种非常简单的方法”。它应该很容易重现,我还给出了 echo 测试客户端的输出,它可以调用相同的 websocket 服务器并返回一个 blob。只要 SO 允许,我会在 6 小时内添加赏金。

标签: java node.js websocket tyrus


【解决方案1】:

最后换了TallNate,这个问题就不存在了。

我在计时后发现它总是在 30 秒后断开我的连接。通常响应比 30 多岁要快,所以我不确定为什么它会挂起然后断开连接。我尝试在 Tyrus 中设置超时,但它仍然在 30 秒时断开连接。最后我尝试了 TallNate 看看我是否可以在那里设置超时......并且开箱即用。

https://github.com/TooTallNate/Java-WebSocket/wiki/Drafts

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
相关资源
最近更新 更多