2015-12-26 16 views
5

Desidero connettermi allo Push API of Poloniex. Sulla loro pagina scrivono quanto segue:Connessione a Poloniex Push-API

Per utilizzare l'API push, connettersi a wss: //api.poloniex.com e iscriversi al feed desiderato.

WSS = WebSocket sicuro -> SSL protette

danno anche un esempio per Node.js e Autobahn | JS:

var autobahn = require('autobahn'); 
var wsuri = "wss://api.poloniex.com"; 
var connection = new autobahn.Connection({ 
    url: wsuri, 
    realm: "realm1" 
}); 

connection.onopen = function (session) { 
     function marketEvent (args,kwargs) { 
       console.log(args); 
     } 
     function tickerEvent (args,kwargs) { 
       console.log(args); 
     } 
     function trollboxEvent (args,kwargs) { 
       console.log(args); 
     } 
     session.subscribe('BTC_XMR', marketEvent); 
     session.subscribe('ticker', tickerEvent); 
     session.subscribe('trollbox', trollboxEvent); 
} 

connection.onclose = function() { 
    console.log("Websocket connection closed"); 
} 

connection.open(); 

Tuttavia, non voglio usare JavaScript , invece uso C++. C'è anche una libreria Autobahn per C++, chiamata Autobahn|CPP. Ho installato e provato a fare funzionare il loro subscriber example code con piccole modifiche (fondamentalmente solo hardcoded l'indirizzo e la porta):

#include <autobahn/autobahn.hpp> 
#include <boost/asio.hpp> 
#include <iostream> 
#include <memory> 
#include <tuple> 

void topic1(const autobahn::wamp_event& event) 
{ 
    std::cerr << "received event: " << event.argument<uint64_t>(0) << std::endl; 
} 
using namespace boost; 
using namespace boost::asio; 
using namespace boost::asio::ip; 
int main() 
{ 
    try { 

     boost::asio::io_service io; 
     boost::asio::ip::tcp::socket socket(io); 

     bool debug = true; 
     auto session = std::make_shared< 
       autobahn::wamp_session<boost::asio::ip::tcp::socket, 
       boost::asio::ip::tcp::socket>>(io, socket, socket, debug); 

     boost::future<void> start_future; 
     boost::future<void> join_future; 

     boost::asio::ip::tcp::endpoint rawsocket_endpoint(boost::asio::ip::address::from_string("173.236.42.218"), 443/*8000=standard*/); 


     socket.async_connect(rawsocket_endpoint, 
      [&](boost::system::error_code ec) { 
       if (!ec) { 
        std::cerr << "connected to server" << std::endl; 

        start_future = session->start().then([&](boost::future<bool> started) { 
         if (started.get()) { 
          std::cerr << "session started" << std::endl; 
          join_future = session->join("realm1").then([&](boost::future<uint64_t> s) { 
           std::cerr << "joined realm: " << s.get() << std::endl; 
           session->subscribe("ticker", &topic1); 
          }); 
         } else { 
          std::cerr << "failed to start session" << std::endl; 
          io.stop(); 
         } 
        }); 
       } else { 
        std::cerr << "connect failed: " << ec.message() << std::endl; 
        io.stop(); 
       } 
      } 
     ); 

     std::cerr << "starting io service" << std::endl; 
     io.run(); 
     std::cerr << "stopped io service" << std::endl; 
    } 
    catch (std::exception& e) { 
     std::cerr << e.what() << std::endl; 
     return 1; 
    } 

    return 0; 
} 

ci sono alcune cose da spiegare qui: ho scoperto l'IP-Adress 173,236 .42.218 semplicemente facendo un ping su api.poloniex.com.

La porta 443 è la porta SSL standard. Ho provato a utilizzare la porta standard WAMP/WebSocket che è 8000, ma il server non lo accetta. 80 non è accettato

Quindi se inizio il programma, l'output è il seguente:

l'avvio del servizio IO

collegato al server di

Poi, non succede nulla. Quindi il codice deve essere bloccato a session_start(), in cui si svolge la stretta di mano WS, ciò che si può vedere quando si guarda in wamp_session.ipp alla linea 80.

A mio parere il problema è che l'API vuole utilizzare un connessione sicura (ws s: //). Sembra che questo pezzo di codice non provi a creare una connessione crittografata con SSL e non so come dire alla sessione che ho bisogno di una connessione sicura.

Edit: In this question l'autore dice che Autobahn non può gestire i server HTTP/WAMP misti in cui e aggiornare http-request è richiesto prima di utilizzare il protocollo WebSocket. So che Poloniex usa un tipo così misto, ma ho provato ad accedere all'API con Autobahn | JS già e lì funziona bene, inviando anche la richiesta di aggiornamento. Quindi forse questa è un'autostrada | CPP problema?

Modifica 2: Se quanto sopra è vero, è possibile inviare Http-Update-Request me stesso e forse anche inserire una crittografia SSL sulla connessione? Non sono sicuro perché forse questo potrebbe interferire con la biblioteca.

risposta

7

No, no, no questo è una risposta tardiva. In ritardo o no, credo che potrebbe essere una soluzione un po 'più diretta per te Bobface (e tutti gli altri che hanno faticato con questo). Esito a dare questo fuori, in quanto sarà potenzialmente utilizzato dai concorrenti. Ma cos'è la vita senza concorrenza !? Noioso, ecco cosa. Inoltre, vorrei che qualcuno fosse venuto prima di me e l'avesse postato, quindi eccoti qui! Sii il cambiamento che desideri vedere, giusto?

Di seguito è disponibile un'implementazione che utilizza websocketpp e autobahn | cpp per connettersi all'APP push di Poloniex. In questo caso, riceverà gli aggiornamenti apportati ai libri per BTC_ETH.

In generale, è possibile utilizzare websocketpp e autobahn | cpp per connettersi a un server socket Web sicuro che implementa il protocollo WAMP (noto anche come wss: //ip-address.com: port).

Cheers!

Include:

#include <autobahn/autobahn.hpp> 
#include <autobahn/wamp_websocketpp_websocket_transport.hpp> 
#include <websocketpp/config/asio_no_tls_client.hpp> 
#include <websocketpp/client.hpp> 
#include <boost/version.hpp> 
#include <iostream> 
#include <memory> 
#include <string> 
#include <tuple> 

Codice:

typedef websocketpp::client<websocketpp::config::asio_tls_client> client; 
typedef autobahn::wamp_websocketpp_websocket_transport<websocketpp::config::asio_tls_client> websocket_transport; 

try { 
    //std::cerr << "Connecting to realm: " << parameters->realm() << std::endl; 

    boost::asio::io_service io; 
    //bool debug = parameters->debug(); 

    client ws_client; 
    ws_client.init_asio(&io); 
    ws_client.set_tls_init_handler([&](websocketpp::connection_hdl) { 
     return websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tlsv12_client); 
    }); 
    auto transport = std::make_shared < autobahn::wamp_websocketpp_websocket_transport<websocketpp::config::asio_tls_client> >(
      ws_client, "wss://api.poloniex.com:443", true); 

    // create a WAMP session that talks WAMP-RawSocket over TCP 
    auto session = std::make_shared<autobahn::wamp_session>(io, true); 

    transport->attach(std::static_pointer_cast<autobahn::wamp_transport_handler>(session)); 

    // Make sure the continuation futures we use do not run out of scope prematurely. 
    // Since we are only using one thread here this can cause the io service to block 
    // as a future generated by a continuation will block waiting for its promise to be 
    // fulfilled when it goes out of scope. This would prevent the session from receiving 
    // responses from the router. 
    boost::future<void> connect_future; 
    boost::future<void> start_future; 
    boost::future<void> join_future; 
    boost::future<void> subscribe_future; 
    connect_future = transport->connect().then([&](boost::future<void> connected) { 
     try { 
      connected.get(); 
     } catch (const std::exception& e) { 
      std::cerr << e.what() << std::endl; 
      io.stop(); 
      return; 
     } 

     std::cerr << "transport connected" << std::endl; 

     start_future = session->start().then([&](boost::future<void> started) { 
      try { 
       started.get(); 
      } catch (const std::exception& e) { 
       std::cerr << e.what() << std::endl; 
       io.stop(); 
       return; 
      } 

      std::cerr << "session started" << std::endl; 

      join_future = session->join("realm1").then([&](boost::future<uint64_t> joined) { 
       try { 
        std::cerr << "joined realm: " << joined.get() << std::endl; 
       } catch (const std::exception& e) { 
        std::cerr << e.what() << std::endl; 
        io.stop(); 
        return; 
       } 

       subscribe_future = session->subscribe("BTC_ETH", &on_topic1).then([&] (boost::future<autobahn::wamp_subscription> subscribed) 
       { 
        try { 
         std::cerr << "subscribed to topic: " << subscribed.get().id() << std::endl; 
        } 
        catch (const std::exception& e) { 
         std::cerr << e.what() << std::endl; 
         io.stop(); 
         return; 
        } 

       }); 
      }); 
     }); 
    }); 

    std::cerr << "starting io service" << std::endl; 
    io.run(); 
    std::cerr << "stopped io service" << std::endl; 
} 
catch (std::exception& e) { 
    std::cerr << "exception: " << e.what() << std::endl; 
    ret_var.successfully_ran = false; 
    return ret_var; 
} 
+0

connessione spesso non viene stabilita .. subito, appena la terza volta ... – Aftershock

+0

Sì, ho notato che di recente con questa soluzione (e altre soluzioni che ho scritto su node js e Java). Se qualcuno ha una soluzione a questo (oltre a ottenere poloniex per ottenere il loro handshake (risposte) di ssl per essere più veloce), per favore fatemelo sapere. – Xandrix

+0

È possibile aumentare un'impostazione ... il tempo di attesa per l'handshake in qualche modo? – Aftershock

1

So che questa è una risposta piuttosto tardiva alla domanda, ma sembra che il problema è che non si sta eseguendo l'aggiornamento HTTP/Websocket al momento della connessione al server remoto. Il codice di esempio che si sta utilizzando è configurato con il trasporto rawsocket_endpoint, che suppongo significhi che non vi è alcun aggiornamento Websocket HTTP o incapsulamento Websocket. Non credo che il tuo problema abbia nulla a che fare con SSL.

Per far funzionare le connessioni Websocket, è necessario rivedere lo AutobahnCPP example che utilizza Websocketpp.