Qt websockets to connect to Pusher service - c++

I have a javascript snippet that connects to a pusher service that I need to convert to c++
<script src="//js.pusher.com/2.2/pusher.min.js" type="text/javascript"></script>
<script type="text/javascript">
var pusher = new Pusher("cb65d0a7a72cd94adf1f");
var channel = pusher.subscribe("ticker.155");
channel.bind("message", function(data) {
//console.log(data);
var topbuy = data.trade.topbuy;
var topsell = data.trade.topsell;
console.log("Buy Price: ", topbuy.price,
"Buy Quantity:", topbuy.quantity),
console.log("Sell Price: ", topsell.price,
"Sell Quantity:", topsell.quantity);
});
</script>
I was able to bust open the connection packet to get a little idea of what is going on http://i.imgur.com/4iYIdLz.png But I can't seem to get a connection.
socketclass.cpp
#include "socketclass.h"
socketClass::socketClass(QObject *parent) :
QObject(parent)
{
}
void socketClass::Test()
{
socket = new QTcpSocket(this);
connect(socket,SIGNAL(connected()), this, SLOT(connected()));
connect(socket,SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(socket,SIGNAL(readyRead()), this, SLOT(readyRead()));
connect(socket,SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWritten(qint64)));
qDebug() << "......Connecting";
socket->connectToHost("ws.pusherapp.com/app/cb65d0a7a72cd94adf1f?protocol=7&client=js&version=2.2.3&flash=false",80);
if(!socket->waitForConnected(1000))
{
qDebug() << "Error: " << socket->errorString();
}
}
void socketClass::connected()
{
//meat and potatoes goes here
qDebug() << "......Connected";
//socket->write("HEAD / HTTP/1.0\r\n\r\n\r\n");
socket->event();
}
void socketClass::disconnected()
{
qDebug() << "......Disconnected";
}
void socketClass::bytesWritten (qint64 bytes)
{
qDebug() << "We wrote: " << bytes;
}
void socketClass::readyRead()
{
qDebug() << "Reading..,,";
qDebug() << socket->readAll();
}
socketclass.h
#ifndef SOCKETCLASS_H
#define SOCKETCLASS_H
#include <QDebug>
#include <QObject>
#include <QTcpSocket>
#include <QAbstractSocket>
class socketClass : public QObject
{
Q_OBJECT
public:
explicit socketClass(QObject *parent = 0);
void Test();
signals:
public slots:
void connected();
void disconnected();
void bytesWritten (qint64 bytes);
void readyRead();
private:
QTcpSocket *socket;
};
#endif // SOCKETCLASS_H
main.cpp
#include <QCoreApplication>
#include "socketclass.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
socketClass mTest;
mTest.Test();
return a.exec();
}
What are the proper connection parameters I should use with c++ websockets to emulate the Javascript?
I am just trying to receive the ticker data and assign it to an object or variable.

My Qt experience is a bit old, but from what I see you won't get the signals since you don't have an event loop running. You should not use the waitForConnected call, you should either run the a.exec() and let take it care of pumping the events. The only thing that seems weird is that you call the waitForConnected, most likely get an an error but still call a.exec()
but don't get the signals after that (or maybe you are stopping the application after the failure?).

Related

I can't see the ip address using QHostAddress::LocalHost through UDP with QUdpSocket

i'm planning do a little app desktop with Qt Creator. I'm using QUdpSocket class to make a simple connection through UDP, in fact i used a test code i found on internet, but my problem is when i run the code and the console just show me the port and the message, not the ip address where come from the message. Could someone tell me what i'm doing bad?
The source reference is this
This is the header file:
#ifndef PRUEBAUDP_H
#define PRUEBAUDP_H
#include <QObject>
#include <QUdpSocket>
#include <QDebug>
/*#include <QNetworkDatagram>
#include <QHostAddress>*/
class pruebaUDP : public QObject
{
Q_OBJECT
public:
explicit pruebaUDP(QObject *parent = nullptr);
void mensajeSocket();
signals:
public slots:
void readyRead();
private:
QUdpSocket *udpSocket;
};
#endif // PRUEBAUDP_H
This is the source file:
#include "pruebaudp.h"
pruebaUDP::pruebaUDP(QObject *parent) : QObject(parent)
{
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::LocalHost, 1234);
connect(udpSocket, SIGNAL(readyRead()),
this, SLOT(readyRead()));
}
void pruebaUDP::mensajeSocket()
{
QByteArray dato;
dato.append("hola");
udpSocket->writeDatagram(dato, QHostAddress::LocalHost, 1234);
}
void pruebaUDP::readyRead()
{
QByteArray buffer;
buffer.resize(udpSocket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
udpSocket->readDatagram(buffer.data(), buffer.size(), &sender, &senderPort);
qDebug() << "Desde: " << sender.toString();
qDebug() << "mensaje del puerto: " << senderPort;
qDebug() << "mensaje: " << buffer;
}
and this is the main file:
#include <QCoreApplication>
#include "pruebaudp.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
pruebaUDP prueba;
prueba.mensajeSocket();
return a.exec();
}
This is a input screenshot:
You use same socket for sending and receiving.
Try to send data via other socket, i.e.
void pruebaUDP::mensajeSocket()
{
QByteArray dato;
dato.append("hola");
static QUdpSocket * socket = new QUdpSocket(this);
socket->writeDatagram(dato, QHostAddress::LocalHost, 1234);
}

how to send an audio stream via tcp in a thread in Qt?

I'm trying to send an audio stream from a microphone via TCP in a thread other than the main thread. Therefore I've set up a server an I'm listening for incoming connections. Once a client connects, I want to send it the audio stream. I've read the Qt Documentation about QTcpServer, Multithreading, and QtMultimedia. I've also looked at this website for example code about multithreading and TCP servers in Qt. The problem is this message that I get during runtime:
QObject: Cannot create children for a parent that is in a different thread. (Parent is QNativeSocketEngine(0xae802a78), parent's thread is MyThread1(0x1856d28), current thread is QThread(0x1838aa0)
this is my code:
in file myserver.h
#ifndef MYSERVER_H
#define MYSERVER_H
#include <QtNetwork>
#include <QTcpServer>
#include <mythread.h>
#include <QtMultimediaKit/QAudioFormat>
#include <QtMultimediaKit/QAudioInput>
#include <QtMultimediaKit/QAudioDeviceInfo>
class MyServer : public QTcpServer
{
Q_OBJECT
public:
explicit MyServer(QObject *parent = 0);
void startServer();
signals:
public slots:
protected:
void incomingConnection(int socketDescriptor);
private:
QAudioInput *audioInput;
};
#endif // MYSERVER_H
in file myserver.cpp
#include "myserver.h"
MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
}
void MyServer::startServer()
{
int port = 12345;
QString ipAddress;
QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
for (int i = 0; i < ipAddressesList.size(); ++i)
{
if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address())
{
ipAddress = ipAddressesList.at(i).toString();
break;
}
}
if(!this->listen( QHostAddress(ipAddress),port ) )
{
qDebug() << "Could not start server";
}
else
{
qDebug() << "The server is running on\n\nIP: "<< ipAddress;
qDebug() << "\nport: " << this->serverPort() << "\n\n";
}
}
void MyServer::incomingConnection(int socketDescriptor)
{
qDebug() << socketDescriptor << " Connecting...";
QAudioFormat format;
format.setSampleRate(44100);
format.setChannelCount(1);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
if (!info.isFormatSupported(format))
{
qWarning()<<"default format not supported try to use nearest";
format = info.nearestFormat(format);
}
audioInput = new QAudioInput(format, this);
MyThread1 *thread = new MyThread1(socketDescriptor,audioInput, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
in file mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QTcpSocket>
#include <QDebug>
#include <QtMultimediaKit/QAudioInput>
class MyThread1 : public QThread
{
Q_OBJECT
public:
explicit MyThread1( int ID, QAudioInput *spk, QObject *parent = 0);
void run();
signals:
void error(QTcpSocket::SocketError socketerror);
public slots:
void sendData();
void disconnected();
private:
QTcpSocket *socket;
int socketDescriptor;
QAudioInput *speaker;
};
#endif // MYTHREAD_H
in file mythread.cpp
#include "mythread.h"
MyThread1::MyThread1( int ID, QAudioInput *spk, QObject *parent) :
QThread(parent)
{
this->socketDescriptor = ID;
this->speaker = spk;
}
void MyThread1::run()
{
qDebug() << " Thread started";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(this->socketDescriptor))
{
emit error(socket->error());
return;
}
connect( speaker->start(), SIGNAL( readyRead() ), this, SLOT( sendData() ) , Qt::DirectConnection);
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
qDebug() << socketDescriptor << " Microphone connected";
exec();
}
void MyThread1::sendData()
{
QByteArray Data = speaker->start()->readAll();
QDataStream l_vStream(&Data, QIODevice::WriteOnly);
l_vStream.setByteOrder(QDataStream::LittleEndian);
socket->write(Data, Data.length());
socket->waitForBytesWritten();
}
void MyThread1::disconnected( )
{
qDebug() << socketDescriptor << "Mic Disconnected";
speaker->stop();
delete speaker;
socket->deleteLater();
exit(0);
}
in file main.cpp
#include <QCoreApplication>
#include <myserver.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyServer server;
server.startServer();
return a.exec();
}
Any help would really be appreciated. Thanks.

C++ Multi-Client TCP Server with QList

Necessary informations:
QList<QTcpSocket*> list;
QTcpServer* server;
QTcpSocket* socket;
In Qt I have built a TCP-Server(QTcpServer)! I have a QList with all my connected clients and I want to read the incomming data for each client personally. So if the QTcpServer gets a new connection, I handel it like this:
void Server::newConnection()
{
qDebug() << "New Connection";
list.append(server->nextPendingConnection());
connect(list.last(),SIGNAL(readyRead()),this,SLOT(readyRead()));
}
How can I get the correct client (out of my QList), which send the SIGNAL readyRead(), in my SLOT readyRead()?
void Server::readyRead(){
//??
}
Any help is welcomed!
Have you tried QObject::sender()? It should return the instance of the QObject which actually sent the signal. Hope that will help.
The solution:
void Server::readyRead(){
QByteArray buffer;
QTcpSocket* readSocket = qobject_cast<QTcpSocket*>(sender());
buffer = readSocket->readAll();
QString mytext = QString::fromStdString(buffer);
qDebug() << mytext;
}
This could be solved by the QSignalMapper. Here is the (not completelly tested) code:
---------------------- main.cpp ------------------
#include "rootwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
RootWindow w;
w.show();
return a.exec();
}
---------------------- rootwindow.h ------------------------
#ifndef ROOTWINDOW_H
#define ROOTWINDOW_H
#include <QMainWindow>
#include <QtDebug>
#include <QLocalServer>
#include <QLocalSocket>
#include <QSignalMapper>
#include <QList>
class RootWindow : public QMainWindow
{
Q_OBJECT
private:
QLocalServer *server;
QLocalSocket *socket;
QList<QLocalSocket*> *list;
QSignalMapper *mapper;
public:
RootWindow(QWidget *parent = 0);
~RootWindow();
private slots:
void slotNewConnection();
void slotReadyRead(int index);
};
#endif // ROOTWINDOW_H
------------------------ rootwindow.cpp -------------------------
#include "rootwindow.h"
RootWindow::RootWindow(QWidget *parent): QMainWindow(parent)
{
server = new QLocalServer;
list = new QList<QLocalSocket*>;
mapper = new QSignalMapper(this);
connect(server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
connect(mapper, SIGNAL(mapped(int)), this, SLOT(slotReadyRead(int)));
server->listen("TestServer");
}
RootWindow::~RootWindow()
{
delete list;
}
void RootWindow::slotNewConnection()
{
qWarning() << "newConnection";
list->append(server->nextPendingConnection());
//here you map each client to its number in the list
mapper->setMapping(list->last(), list->length()-1);
//here we say, that when ever a client from the QList sends readyRead() the mapper should be used
//with the property (list->length()-1) defined in the line above
connect(list->last(), SIGNAL(readyRead()), mapper, SLOT(map()));
}
void RootWindow::slotReadyRead(int index)
{
qWarning() << "Client " << index << " has written: " << list->at(index)->readAll();
}
It's basically your code, I've only added the QSignalMapper and some comments at the relevant lines.

Why does this Qt signal never get emitted?

I am trying to get data out of a web page, but the signal finished() never gets emitted!!! I know I must be doing something wrong, but can't figure out what it is.
# webservice.h
class WebService:public QObject
{
Q_OBJECT
public:
explicit WebService(QObject *parent=0);
void getRequest(const QString &urlString);
signals:
void networkError(QNetworkReply::NetworkError ne);
void finished(QNetworkReply*);
public slots:
void parseNetworkResponse(QNetworkReply* finished);
private:
QNetworkAccessManager *netMgr;
public:
QByteArray data;
};
#webservice.cpp
WebService::WebService(QObject *parent):QObject(parent)
{
netMgr = new QNetworkAccessManager;
connect(netMgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(parseNetworkResponse(QNetworkReply*)));
}
void WebService::getRequest(const QString &urlString)
{
QUrl url(urlString);
QNetworkRequest req;
emit finished(netMgr->get(req));
}
void WebService::parseNetworkResponse(QNetworkReply *finished)
{
if (finished->error() != QNetworkReply::NoError)
{
emit networkError(finished->error());
return;
}
data = finished->readAll();
qDebug() << data;
}
data never gets assigned a value as expected.
You aren't passing the url to the QNetworkRequest you create. Try:
QNetworkRequest req(url);
inside WebService::getRequest().
As requested, here's the source modified to allow it compile and work inside QtCreator as a single main.cpp file in a console application project:
#include <QCoreApplication>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QByteArray>
#include <QString>
#include <QDebug>
//# webservice.h
class WebService:public QObject
{
Q_OBJECT
public:
explicit WebService(QObject *parent=0);
void getRequest(const QString &urlString);
signals:
void networkError(QNetworkReply::NetworkError ne);
void finished(QNetworkReply*);
public slots:
void parseNetworkResponse(QNetworkReply* finished);
private:
QNetworkAccessManager *netMgr;
public:
QByteArray data;
};
//#webservice.cpp
WebService::WebService(QObject *parent):QObject(parent)
{
netMgr = new QNetworkAccessManager;
connect(netMgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(parseNetworkResponse(QNetworkReply*)));
}
void WebService::getRequest(const QString &urlString)
{
QUrl url(urlString);
QNetworkRequest req(url);
emit finished(netMgr->get(req));
}
void WebService::parseNetworkResponse(QNetworkReply *finished)
{
if (finished->error() != QNetworkReply::NoError)
{
qDebug() << "QNetworkReply error: " << finished->error();
emit networkError(finished->error());
return;
}
data = finished->readAll();
qDebug() << data;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WebService web;
web.getRequest("http://www.google.com");
return a.exec();
}
#include "main.moc"
The minor modifications that were made:
added necessary headers
added a main() that called WebService::getRequest() with an appropriate URL
added #include "main.moc" to the end of the main.cpp file so qmake would "moc-ify" it properly as a single, self-contained .cpp file
made the fix mentioned above in the answer to the question
added a qDebug() output in the error case
One final thing that needed to be done was to add QT += network in the .pro file for the project so the Qt networking modules get added to the link step and to the header search path.
Update 15 Oct 2013
From your comments, it looks like you want the QNetworkAccessManager::get() call to be synchronous. I've added another version of your example program that will block in WebService::getRequest() until the request's finished signal is received. Note that this example doesn't perform much in the way of error handling, and would probably perform very badly if the netwrok request fails to complete in a timely manner. Dealing apprpriately with errors and timeouts would be necessary for anything but example or study code.
The basic idea in this example is that the signals emitted in the asynchronous Qt networking model are driven by the framework's event loop. So when a request is made, a new 'nested' event loop is created and the WebService::getRequest() function execs that loop (and stays there) until the handler of the finished signal tells the event loop to exit.
#include <QCoreApplication>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QEventLoop>
#include <QByteArray>
#include <QString>
#include <QDebug>
//# webservice.h
class WebService:public QObject
{
Q_OBJECT
public:
explicit WebService(QObject *parent=0);
void getRequest(const QString &urlString);
signals:
void networkError(QNetworkReply::NetworkError ne);
//void finished(QNetworkReply*);
public slots:
void parseNetworkResponse(QNetworkReply* finished);
private:
QNetworkAccessManager *netMgr;
QEventLoop request_event_loop;
public:
QByteArray data;
};
//#webservice.cpp
WebService::WebService(QObject *parent):QObject(parent)
{
netMgr = new QNetworkAccessManager;
connect(netMgr, SIGNAL(finished(QNetworkReply*)),
this, SLOT(parseNetworkResponse(QNetworkReply*)));
}
void WebService::getRequest(const QString &urlString)
{
QUrl url(urlString);
QNetworkRequest req(url);
netMgr->get(req);
request_event_loop.exec(); // wait here until the WebService::parseNetworkResponse() slot runs
// emit finished(netMgr->get(req));
}
void WebService::parseNetworkResponse(QNetworkReply *finished)
{
qDebug() << "enter parseNetworkResponse()";
if (finished->error() != QNetworkReply::NoError)
{
qDebug() << "QNetworkReply error: " << finished->error();
emit networkError(finished->error());
}
else {
data = finished->readAll();
qDebug() << data;
}
qDebug() << "request_event_loop.exit()";
request_event_loop.exit();
qDebug() << "exit parseNetworkResponse()";
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WebService web;
qDebug() << "main() getRequest()";
web.getRequest("http://www.stackoverflow.com");
qDebug() << "main() getRequest() completed";
return a.exec();
}
#include "main.moc"

Console Chat Using QTcpSocket and QTcpServer

I want to write a console chat program in qt framework.I have a problem with sending messages.
Client sends messages to server but server doesn't take the messages until client program is closed.When client is closed, server displays all messages.I don't want that.I want server to get my messages when i send to it.
I wrote the codes below.You will see what i want to do if you look at main function of client.
/*
Created BY :
Creation DATE : 26/10/2012
Client interface
*/
#ifndef CLIENT_H
#define CLIENT_H
#include <QtNetwork>
#include <QObject>
#include <QtNetwork/QTcpSocket>
namespace NetworkArdic
{
class Client : public QObject
{
Q_OBJECT
public:
Client(QObject * obj = 0,QString add="localhost", quint16 port = 4000);
void SendData(QString data);
virtual ~Client();
private slots:
void ReadData();
void connected();
private:
QTcpSocket *socket;
};
}
#endif
/*
Created BY :
Creation DATE : 26/10/2012
Client source file
*/
#include "Client.h"
#include <QHostAddress>
#include <iostream>
using namespace std;
namespace NetworkArdic{
Client::Client(QObject * obj, QString add, quint16 port) : QObject(obj)
{
socket = new QTcpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(ReadData()));
connect(socket, SIGNAL(connected()), this, SLOT(connected()));
socket->connectToHost(QHostAddress(add), port);
}
Client::~Client(){
socket->close();
delete socket;
}
void Client::SendData(QString data)
{
if(!data.isEmpty())
{
socket->write(QString(data + "\n").toUtf8());
}
}
void Client::ReadData()
{
while(socket->canReadLine())
{
QString line = QString::fromUtf8(socket->readLine()).trimmed();
qDebug() << line;
}
}
void Client::connected()
{
socket->write(QString("Client : Server connection has been made (: \n").toUtf8());
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Client cli(0,"127.0.0.1",4000);
string line;
while(line!="exit"){
cout << "Message : ";
cin >> line;
cli.SendData(QString(line.c_str()));
}
return a.exec();
}
/*
Created BY :
Creation DATE : 26/10/2012
Server interface
*/
#ifndef SERVER_H
#define SERVER_H
#include <QtNetwork>
#include <QObject>
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
namespace NetworkArdic
{
class Server: public QTcpServer
{
Q_OBJECT
public:
Server(QObject * parent = 0 , quint16 port = 4000);
virtual ~Server();
private slots:
void acceptConnection();
void startRead();
void disconnected();
private:
QTcpSocket * client;
};
}
#endif // SERVER_H
/*
Created BY :
Creation DATE : 26/10/2012
Server source file
*/
#include "Server.h"
#include <iostream>
using namespace std;
namespace NetworkArdic{
Server::Server(QObject* parent , quint16 port): QTcpServer(parent)
{
connect(this, SIGNAL(newConnection()),this, SLOT(acceptConnection()));
listen(QHostAddress::Any, port );
}
Server::~Server()
{
delete client;
close();
}
void Server::acceptConnection()
{
client = nextPendingConnection();
connect(client, SIGNAL(readyRead()), this, SLOT(startRead()));
connect(client, SIGNAL(disconnected()), this, SLOT(disconnected()));
qDebug() << "New client from:" << client->peerAddress().toString();
}
void Server::startRead()
{
while(client->canReadLine())
{
QString line = QString::fromUtf8(client->readLine()).trimmed();
qDebug() << "Client :" << line;
client->write(QString("Server : I've taken your message (:\n").toUtf8());
}
}
void Server::disconnected()
{
qDebug() << "Client disconnected:" << client->peerAddress().toString();
client->write(QString("Server : I wish you didn't leave ):\n").toUtf8());
}
}
Try using socket->flush() after you write the data.
http://doc.qt.digia.com/qt/qabstractsocket.html#flush
You used the code below to read socket data.
void Server::startRead()
{
while(client->canReadLine())
{
QString line = QString::fromUtf8(client->readLine()).trimmed();
qDebug() << "Client :" << line;
client->write(QString("Server : I've taken your message (:\n").toUtf8());
}
}
I suggest to adopt from the following code which I have tested works
while (tcp_server->hasPendingConnections()) {
client = tcp_server->nextPendingConnection();
client->waitForReadyRead(100);
QByteArray byteArray = client->readAll();
QString s_data = byteArray.data();
// Process s_data
client->close();
client->abort();
}