【问题标题】:Draft refuses handshake when using java-websocket library to connect to the coinbase exchange websocket streamDraft 在使用 java-websocket 库连接到 coinbase exchange websocket 流时拒绝握手
【发布时间】:2016-04-10 05:43:19
【问题描述】:

我正在尝试使用Java-Websocket library by TooTallNate 创建一个从coinbase exchange websocket stream 接收消息的websocket 客户端。由于 Python 中的并行化瓶颈,我正在将我用 Python 制作的程序移植到 Java,并且据我所知,我在 Java 中做的事情与在 Python 中做的事情相同。这是我使用 this websocket lib 在 Python 中打开连接的代码(按预期工作):

ws = websocket.create_connection("wss://ws-feed.exchange.coinbase.com", 20)
            ws.send(json.dumps({
            "type": "subscribe",
            "product_id": "BTC-USD"
        }))

这是我的整个 Java 类:

public class CoinbaseWebsocketClient extends WebSocketClient {

private final Gson gson = new Gson();

private CoinbaseWebsocketClient(URI serverURI) {
    super(serverURI, new Draft_17());
    connect();
}

private static URI uri;
private static CoinbaseWebsocketClient coinbaseWebsocketClient;

static {
    try {
        uri = new URI("wss://ws-feed.exchange.coinbase.com");
    } catch (URISyntaxException e) {
        e.printStackTrace();
    }
}

protected static CoinbaseWebsocketClient get() {
    if (coinbaseWebsocketClient == null) {
        coinbaseWebsocketClient = new CoinbaseWebsocketClient(uri);
    }
    return coinbaseWebsocketClient;
}

@Override
public void onOpen(ServerHandshake serverHandshake) {
    System.out.println("Websocket open");
    final JsonObject btcUSD_Request = new JsonObject();
    btcUSD_Request.addProperty("type", "subscribe");
    btcUSD_Request.addProperty("product_id", "BTC_USD");
    final String requestString = gson.toJson(btcUSD_Request);
    send(requestString);
}

@Override
public void onMessage(String s) {
    System.out.println("Message received: " + s);
}

@Override
public void onClose(int code, String reason, boolean remote) {
    System.out.println("Websocket closed: " + reason);
}

@Override
public void onError(Exception e) {
    System.err.println("an error occurred:" + e);
}

}

我知道我的 Java 代码没有完全根本的问题,因为当我使用 ws://echo.websocket.org 而不是 wss://ws-feed.exchange.coinbase 作为 URI 时,它可以按预期工作.com。但是,当我尝试连接到 wss://ws-feed.exchange.coinbase.com 时,我收到此错误:

Websocket closed: draft org.java_websocket.drafts.Draft_17@7ca2fefb refuses handshake

据我所知,此连接没有任何身份验证或类似的东西(我没有在我的 Python 程序中提供任何身份验证),所以我不知道这个错误的根源是什么。

【问题讨论】:

  • 您是否尝试将 SocketFactory 设置为接受所有 SSL 证书?这就是我(hackily)解决我的 wss 问题的方式

标签: java websocket java-websocket


【解决方案1】:

需要创建如下所示的 sslcontext。它跳过证书。我可以在没有证书的情况下成功建立连接

SSLContext sslContext = SSLContext.getInstance("SSL");

// set up a TrustManager that trusts everything
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                    System.out.println("getAcceptedIssuers =============");
                    return null;
            }

            public void checkClientTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkClientTrusted =============");
            }

            public void checkServerTrusted(X509Certificate[] certs,
                            String authType) {
                    System.out.println("checkServerTrusted =============");
            }
} }, new SecureRandom());

【讨论】:

  • 这不是问题的答案。如果您需要帮助,请发布一个新问题
  • 这应该是一个新问题,而不是评论。但是,如果您想发表评论,请等到您有 15 个代表
  • 添加并回答希望对您有帮助
  • 这解决了我的问题,但答案令人困惑。我提交了包含一些格式调整和实施说明的编辑。
【解决方案2】:

在执行connect()之前需要调用setSocket()方法,例如:

private CoinbaseWebsocketClient(URI serverURI) {
    super(serverURI, new Draft_17());
    setSocket(SSLSocketFactory.getDefault().createSocket(serverURI.getHost(), serverURI.getPort()));
    connect();
}

祝你好运!


注意:请注意,如果出现任何故障,您的单例 get() 可能不是一个好主意(如果我没记错的话,客户端类在不可恢复的错误后无法使用,您必须创建一个新客户端才能恢复)。

【讨论】:

    【解决方案3】:

    vlp 几乎是对的。但是应该将 443 硬编码为端口参数:

    private CoinbaseWebsocketClient(URI serverURI) {
        super(serverURI, new Draft_17());
        setSocket(SSLSocketFactory.getDefault().createSocket(serverURI.getHost(), 443));
        connect();
    }
    

    这对我有用!

    PS。 ssl 必须是一个有效的证书,否则你不能只使用 getDefault 方法来获取 ssl 上下文。自烧等请参考以下链接:

    http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-11
      • 2019-10-17
      • 2011-09-22
      • 2015-04-01
      相关资源
      最近更新 更多