I want to receive updates from websockets defined in the coinbase pro API.
For example I'd like to register the heartbeat channel, that should be received once per second according to documentation.
I've tried to register to the web socket, but I obtain only the subscriptions message in reply:
{"type":"subscriptions","channels":[{"name":"heartbeat","product_ids":["ETH-EUR"]}]}
After that I'm not receiving anything anymore. What should I do in order to listen to the messages of the client
This is the piece of code involved (modified a bit, it's in a class, m_webSocket is a class member that should be used also elsewhere, and it should be closed in the destructor):
void EndpointClient::connectToWebSockets() {
constexpr auto WebSocketFeed{ U("wss://ws-feed.pro.coinbase.com") };
constexpr auto RequestStatus{ "{\"type\": \"subscribe\", \"channels\" : [{ \"name\": \"heartbeat\", \"product_ids\" : [\"ETH-EUR\"] }]}" };
web::websockets::client::websocket_client m_webSocket;
try {
m_webSocket.connect(WebSocketFeed).wait();
auto receivedTast = m_webSocket.receive().then([this](websocket_incoming_message ret_msg) {
auto s = ret_msg.extract_string();
m_logger->info("s = " + s.get());
});
websocket_outgoing_message msg;
msg.set_utf8_message(RequestStatus);
m_webSocket.send(msg).wait();
receivedTast.wait();
m_webSocket.close().wait();
}
catch (websocket_exception& e) {
m_logger->error("coinbase: exception when setting websocket: " + string{ e.what() });
}
catch (std::exception& e) {
m_logger->error("coinbase: exception when setting websocket: " + string{ e.what() });
}
}
The .receive() method only gets one message. If you want to receive more incoming messages, you need to run it in a loop. Or you can use a websocket_callback_client instead so that it can listen automatically (websocket_callback_client.set_message_handler() method).
Related
I'm new to RabbitMQ.
I installed RabbitMQ server on Windows 10. I can login to the server in web browser. When I run the client code below (uses AMQP-CPP library), neigther channel.onSuccess nor channel.onError are called. And, I don't see my declared my-queue queue and my-exchange exchange in the web browser.
If I understood correctly, I need to add some event loop (?). But, I cannot find any example for Windows. Can you explain what can be the issue?
int main()
{
// create an instance of your own tcp handler
MyTcpHandler myHandler;
// address of the server
//AMQP::Address address("amqp://guest:guest#localhost:5672/");
AMQP::Address address("localhost", 15672, AMQP::Login("guest", "guest"), "");
// create a AMQP connection object
AMQP::TcpConnection connection(&myHandler, address);
// and create a channel b
AMQP::TcpChannel channel(&connection);
// use the channel object to call the AMQP method you like
channel.declareExchange("my-exchange", AMQP::fanout)
.onSuccess([]()
{
std::cout << "declared exchange " << std::endl;
}).onError([](const char *message)
{
std::cout << "error: " << message << std::endl;
});
channel.declareQueue("my-queue");
channel.bindQueue("my-exchange", "my-queue", "my-routing-key");
std::cout << "Press Enter..." << std::endl;
std::getchar();
return 0;
}
MyTcpHandler
class MyTcpHandler : public AMQP::TcpHandler
{
public:
virtual void onConnected(AMQP::TcpConnection *connection) {}
virtual void onError(AMQP::TcpConnection *connection, const char *message) {}
virtual void onClosed(AMQP::TcpConnection *connection) {}
virtual void monitor(AMQP::TcpConnection *connection, AMQP::tcp::Socket fd, int flags) {}
};
came across same issue myself today.
The problem is you have to implement your own hanlder, or nothing will be sent.
The bundled TcpHandler is based on boost asio tcpHandler which is posix only, and will not compile on windows. see this link
Too shame it's doesn't have internal built-in handler, this is so "basic"...
You are connecting on the wrong port 15672 is the management plugin port , you need to connect on Port 5672 which is the AMQP port
Please correct the code as under
AMQP::Address address("localhost", 5672, AMQP::Login("guest", "guest"), "");
You could just use HareDu 2 Broker API to do it using the below code. Docs can be found here: https://github.com/ahives/HareDu2
var result = _container.Resolve<IBrokerObjectFactory>()
.Object<Queue>()
.Create(x =>
{
x.Queue("your_queue");
x.Configure(c =>
{
c.IsDurable();
c.AutoDeleteWhenNotInUse();
c.HasArguments(arg =>
{
arg.SetQueueExpiration(1000);
arg.SetPerQueuedMessageExpiration(2000);
});
});
x.Targeting(t =>
{
t.VirtualHost("your_vhost");
t.Node("your_node");
});
});
When client create an instant on SenderThread. It can send data to and from.
But when client goes for suspend mode and come back from suspend. The last created threads get exception on
resume. and no data is sent.
Exception Details received :
displayText = Exception
message =
name = Exception
className = N4Poco9ExceptionE
Here is the code:
class SenderThread: public Poco::Runnable
{
public:
MyThread(const std::string& msg):
Msg(msg);
{
}
void run()
{
try {
SendData(msg);
} catch(Exception exp) {
std::cout<<"displayText = "<<e.displayText()<<std::endl;
std::cout<<"message = "<<e.message()<<std::endl;
std::cout<<"name = "<<e.name()<<std::endl;
std::cout<<"className = "<<e.className()<<std::endl;
}
}
private:
std::string Msg;
};
How can I get more details on the exception and how to handle this exception?.
Edited After Günter Obiltschnig comment:
I am able to catch the proper exception.
displayText = Invalid argument
name = Invalid argument
Some time i see socket closed exception. When system goes to suspend mode then all the socket is closed by system(os). Now upon resume application tries to open the socket again it throw error in the Poco::Net::Socket::Socket(Poco::Net::Socket const&). any help on this please
You have to catch the exception by (const) reference in order to get useful information out of it.
catch (const Poco::Exception& exc)
{
std::cerr << exc.displayText() << std::endl;
}
I'm trying to send an email using the Poco Net library with this code (my credentials are arbitrary obviously):
void send_email() {
// Poco::Net::SMTPClientSession session("localhost", 465);
const std::string& smtp_host {"mail.example.com"};
const std::string& smtp_user {"marinos#example.com"};
const std::string& smtp_passwd {"myPassword"};
std::string to = "marinos#example.com";
std::string from = "marinos#example.com";
std::string subject = "Your first e-mail message sent using Poco Libraries";
subject = Poco::Net::MailMessage::encodeWord(subject, "UTF-8");
std::string content = "Well done! You've successfully sent your first message using Poco SMTPClientSession";
Poco::Net::MailMessage message;
message.setSender(from);
message.addRecipient(Poco::Net::MailRecipient{Poco::Net::MailRecipient::PRIMARY_RECIPIENT, to});
message.setSubject(subject);
message.setContentType("text/plain; charset=UTF-8");
message.setContent(content, Poco::Net::MailMessage::ENCODING_8BIT);
try {
Poco::Net::SMTPClientSession session(smtp_host, 465);
session.open(); // this is where it halts
try {
session.login(Poco::Net::SMTPClientSession::AUTH_LOGIN, smtp_user, smtp_passwd);
session.sendMessage(message);
std::cout << "Message successfully sent" << std::endl;
session.close();
} catch (Poco::Net::SMTPException& e) {
std::cerr << e.displayText() << std::endl;
session.close();
}
} catch (Poco::Net::NetException& e) {
std::cerr << e.displayText() << std::endl;
}
}
and my program simply halts. I've used a debugger to locate the problem and it seems that the program halts when calling session.open(). Am I doing something wrong here?
Since I do not know specification of your SMTP server, I am speculating that you're probably suppose to use SMTPS instead of plain SMTP, because port 465 is default port for SMTPS (according to Wikipedia). I guess the program halts during SSL handshaking. By looking into Poco documentation I see that there exists SSL version of the Poco::Net::SMTPClientSession. Thus, you should try with SecureSMTPClientSession. Check if your mail server requires START_TLS, in that case I guess you should additionally call bool startTLS().
I have this piece of code as part of a socks5 proxy server implementation. This is the part from where once the server established communication sockets with proxy client (in code - socket_) and destination server (in code clientSock_) it takes data send on a socket and exchanges it with data sent on the other socket.
I specify that this exchange happens already in a thread spawn by the server for a proxy client.
std::size_t readable = 0;
boost::asio::socket_base::bytes_readable command1(true);
boost::asio::socket_base::bytes_readable command2(true);
try
{
while (1)
{
socket_->io_control(command1);
clientSock_->io_control(command2);
if ((readable = command1.get()) > 0)
{
transf = ba::read(*socket_, ba::buffer(data_,readable));
ba::write(*clientSock_, ba::buffer(data_,transf));
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
}
if ((readable = command2.get()) > 0)
{
transf = ba::read(*clientSock_, ba::buffer(data_,readable));
ba::write(*socket_, ba::buffer(data_,transf));
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
}
}
}
catch (std::exception& ex)
{
std::cerr << "Exception in thread while exchanging: " << ex.what() << "\n";
return;
}
The problem here is that I have very high CPU in the loop. Also I am not sure if here the way to know if one of the parts has closed the socket is to catch boost socket exception -> and end the data exchange.
The problem ca be solved by using asynchronous write/read functions. Basically use async_read_some() or async_write() - or other async functions in these categories. Also in order for async processing to work one must call io_service.run() after at least one async function was called - that will dispatch completion handler for async processing.
I started to program client/server applications in J2ME recently.Now I'm working with c++ builder 2010 indy components (e.g. TidTTCPServer) and J2ME. My application is designed to restart the kerio winroute firewall service from a remote machine.
My server application is written in c++ builder 2010, I've put a TidTCTServer component into a form which binded to 127.0.0.1:4500. That's listening on port 4500 in local machine.
Then i've added a listbox that i need to add every upcoming packets converted to UnicodeString.
//void __fastcall TForm1::servExecute(TIdContext *AContext)
UnicodeString s;
UnicodeString txt;
txt=Trim(AContext->Connection->IOHandler->ReadLn());
otvet->Items->Add(txt);
otvet->ItemIndex=otvet->Items->Count-1;
if (txt=="1") {
AContext->Connection->IOHandler->WriteLn("Suhrob");
AContext->Connection->Disconnect();
}
if (txt=="2") {
AContext->Connection->IOHandler->WriteLn("Shodi");
AContext->Connection->Disconnect();
}
//----------------------------------------------------------------------------
// void __fastcall TForm1::servConnect(TIdContext *AContext)
++counter;
status->Panels->Items[0]->Text="Connections:" + IntToStr(counter);
status->Panels->Items[1]->Text="Connected to " + AContext->Connection->Socket->Binding->PeerIP + ":" + AContext->Connection->Socket->Binding->PeerPort;
and my client side code looks smth like this:
else if (command == send) {
// write pre-action user code here
InputStream is=null;
OutputStream os=null;
SocketConnection client=null;
ServerSocketConnection server=null;
try {
server = (ServerSocketConnection) Connector.open("socket://"+IP.getString()+":"+PORT.getString());
// wait for a connection
client = (SocketConnection) Connector.open("socket://"+IP.getString()+":"+PORT.getString());
// set application-specific options on the socket. Call setSocketOption to set other options
client.setSocketOption(SocketConnection.DELAY, 0);
client.setSocketOption(SocketConnection.KEEPALIVE, 0);
is = client.openInputStream();
os = client.openOutputStream();
// send something to server
os.write("texttosend".getBytes());
// read server response
int c = 0;
while((c = is.read()) != -1) {
// do something with the response
System.out.println((char)c);
}
// close streams and connection
}
catch( ConnectionNotFoundException error )
{
Alert alert = new Alert(
"Error", "Not responding!", null, null);
alert.setTimeout(Alert.FOREVER);
alert.setType(AlertType.ERROR);
switchDisplayable(alert, list);
}
catch (IOException e)
{
Alert alert = new Alert("ERror", e.toString(), null, null);
alert.setTimeout(Alert.FOREVER);
alert.setType(AlertType.ERROR);
switchDisplayable(alert, list);
e.printStackTrace();
}
finally {
if (is != null) {
try {
is.close();
} catch (Exception ex) {
System.out.println("Failed to close is!");
}
try {
os.close();
} catch (Exception ex) {
System.out.println("Failed to close os!");
}
}
if (server != null) {
try {
server.close();
} catch (Exception ex) {
System.out.println("Failed to close server!");
}
}
if (client != null) {
try {
client.close();
} catch (Exception ex) {
System.out.println("Failed to close client!");
}
}
}
my client application gets connected with the server but when i try to send data such as
os.write("texttosend".getBytes());
I cannot get text data on the server using. That's I am not getting sent packets in the server from client.
txt=Trim(AContext->Connection->IOHandler->ReadLn());
Guys, where am I wrong? is the way i'm doing is ok?
Or do I need to use StreamConnection instead of SocketConnection?
And when i use telnet to send data it works cool, strings will be added to listbox
telnet 127.0.0.1 4500
texttosend
23
asf
Any help is appreciated !!!
Thanks in advance!
The main problem is that you are using ReadLn() on the server end. ReadLn() does not exit until a data terminator is encountered (a LF line break character is the default terminator) or if a reading timeout occurs (Indy uses infinite timeouts by default). Your J2ME code is not sending any data terminator, so there is nothing to tell ReadLn() when to stop reading. The reason it works with Telnet is because it does send line break characters.
The other problem with your code is that TIdTCPServer is a multi-threaded component, but your code is updating the UI components in a thread-unsafe manner. You MUST synchronize with the main thread, such as by using Indy's TIdSync and/or TIdNotify classes, in order to update your UI safely from inside of the server's event handlers.
Yes, flush method is necessary to call after sending bytes, but ..... finally....
then i tried to include my connection code in a new thread that implements Runnable worked perfectly. Now I've found where I was wrong!!!!!!!!!!!!!!
That's guys you need to include above code in the following block.
Thread t= new Thread(this);
t.start();
public void run()
{
//here paste the code
}
Try OutputStream.flush()?
If not, try writing to a known working server, instead of one you've created yourself (something like writing "HELO" to an SMTP server), this will help you figure out which end the error is at.