2016-01-06 17 views
15

Sto tentando di utilizzare lo Java-Websocket library by TooTallNate per creare un client websocket che riceve messaggi dallo coinbase exchange websocket stream. Sto eseguendo il porting di un programma che ho realizzato in Python su Java a causa dei colli di bottiglia di parallelizzazione in Python e, a mia conoscenza, sto facendo le stesse cose in Java come in Python. Ecco il mio codice per aprire la connessione in Python utilizzando this websocket lib (Questo funziona come previsto):Draft rifiuta l'handshake quando si utilizza la libreria java-websocket per connettersi allo streaming websocket scambio coinbase

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

Ecco tutta la mia classe 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); 
} 

}

So che ci isn' Un problema assolutamente fondamentale con il mio codice Java perché funziona come previsto quando utilizzo ws: //echo.websocket.org come URI invece di wss: //ws-feed.exchange.coinbase.com. Tuttavia quando provo a connettermi a WSS: //ws-feed.exchange.coinbase.com Ottengo questo errore:

Websocket closed: draft [email protected] refuses handshake 

Non v'è alcuna autenticazione o qualcosa di simile per la connessione per quanto ne so (I didn fornire alcuno nel mio programma Python), quindi sono in perdita per quanto riguarda l'origine di questo errore.

+0

Hai provato impostando la SocketFactory di accettare tutti i certificati SSL? È così che ho risolto il problema con il mio wss –

risposta

0

È necessario chiamare il metodo setSocket() prima di fare la connect(), ad es .:

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

Buona fortuna!


Una nota: Attenzione che il vostro Singleton get() potrebbe non essere una buona idea in caso di eventuali guasti (se non ricordo male la classe cliente è inutilizzabile dopo l'errore irreversibile e si deve creare un nuovo client per il recupero) .

1

È necessario creare sslcontext come di seguito. salta il certificato. Sono riuscito a fare una connessione senza certificato

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()); 
+0

Questa non è una risposta alla domanda. Se hai bisogno di aiuto, invia una nuova domanda –

+0

sì, non sono autorizzato a commentare in altri post. – Prakash

+0

Dovrebbe essere una nuova domanda, non un commento. Ma se vuoi commentare aspetta di avere 15 rep –

0

vlp ha quasi ragione. Ma dovrebbe codificare come parametro di porta:

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

che funziona per me!

PS. ssl deve essere un certificato valido, altrimenti non è possibile utilizzare il metodo getDefault per ottenere il contesto ssl. Per self-bruciacchiato, ecc Si prega di fare riferimento al seguente link:

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