Ok.
Thanks for the reply. QDataStream put out a lot of segfaults outputing to a qint16 data[nbrBytes] ... and I'm really not sure this is the way to go (see below)
Let's start over to see if I can make any sense of this...
I have a device that sends binary data -- 16bit values -- it sends this data all at once.
I'm giving out my code so that someone can help me here...
myunit.h
#ifndef CONNTHREAD_H
#define CONNTHREAD_H
#include <QThread>
#include <QTcpSocket>
#include <server.h>
{
Q_OBJECT
public:
myUnit ( int socketDescriptor, Server *parent );
~myUnit ();
void run ();
char * peerAddress; // Unit's IP
char imei[15]; // unique unit identifier (IMEI)
bool gotImei; // semaphore for determining whether we have the unit's IMEI or not
//SNIP sensitive objects
signals:
void error
( QTcpSocket::SocketError socketError
);
public slots:
void disconnected ();
void incomingData ();
quint64 writeData ();
private:
int socketDescriptor;
protected:
Server *server;
};
#endif
#ifndef CONNTHREAD_H
#define CONNTHREAD_H
#include <QThread>
#include <QTcpSocket>
#include <server.h>
class myUnit : public QThread
{
Q_OBJECT
public:
QTcpSocket tcpSocket;
myUnit ( int socketDescriptor, Server *parent );
~myUnit ();
void run ();
void checkImei (QByteArray &bData);
char * peerAddress; // Unit's IP
char imei[15]; // unique unit identifier (IMEI)
bool gotImei; // semaphore for determining whether we have the unit's IMEI or not
//SNIP sensitive objects
signals:
void error ( QTcpSocket::SocketError socketError );
public slots:
void disconnected ();
void incomingData ();
quint64 writeData ();
private:
int socketDescriptor;
protected:
Server *server;
};
#endif
To copy to clipboard, switch view to plain text mode
myunit.cpp
#include "myunit.h"
#include <iostream>
#include <QtNetwork>
#include <QDebug> // TODO remove in production!
using namespace std;
extern char * toCharP
( QString str
);
myUnit
::myUnit ( int socketDescriptor, Server
*parent
) : QThread ( parent
){
// initialize the unit's socket --> provided by Server::incomingConnection()
if ( !tcpSocket.setSocketDescriptor ( socketDescriptor ) )
{
emit error ( tcpSocket.error() );
return;
}
// this unit doesn't have an IMEI yet...
gotImei=false;
// initialize our imei (000000000000000)
strcpy(imei, "00000000000000");
// access to this parent server object
server=parent;
connect ( &tcpSocket, SIGNAL ( readyRead() ), this, SLOT ( incomingData() ) );
connect ( &tcpSocket, SIGNAL ( disconnected() ), this, SLOT ( disconnected() ) );
}
/**
* myUnit::~myUnit()
* Reimplementation of the QThread's destructor.
* Just to exhibit a message upon this client disconnection.
*/
myUnit::~myUnit()
{
char * dt = toCharP ( getDateTime() );
cout << dt << ": Unit [" << imei << "] disconnected." << " # active clients: " << server->nbrClients << endl;
}
/**
* void myUnit::run()
* Reimplementation of QThread::run().
* Just to exhibit a message upon a new client connection.
* The exec() begins a loop for the thread's events.
*/
void myUnit::run()
{
char * dt = toCharP ( getDateTime() );
peerAddress = toCharP ( tcpSocket.peerAddress().toString() );
cout << dt << ": Incoming connection from [" << peerAddress << "]" << " # clients: " << server->nbrClients << endl;
exec();
}
/**
* void myUnit::disconnected ();
* This function (slot) is connected to the tcpSocket disconnected() signal.
* Decrements the parent server object nbrClients member and exits the thread.
* The quit() insures a graceful exit from the thread, cleaning up child objects and associated memory.
*/
void myUnit::disconnected()
{
server->nbrClients--;
this->quit();
}
/**
* void myUnit::incomingData ();
* This function (slot) is connected to the tcpSocket readyRead() signal, so that when any data is available
* on the socket it's thrown here.
* returns the number of bytes read.
*/
void myUnit::incomingData ()
{
unitData=tcpSocket.readAll();
int nbrBytes = unitData.length();
cout << "Incoming data from [" << peerAddress << "] - Nbr. of bytes: " << nbrBytes;
if (!gotImei) {
cout << " - checking IMEI..." << endl;
checkImei(unitData);
}
else {
cout << " - parsing data..." << endl;
}
}
quint64 myUnit::writeData ()
{
// TODO
return 0;
}
{
unsigned int nBytes = sData.left(2).toUInt();
cout << "nBytes: " << nBytes << endl;
cout << "sData: " << sData.right(15).toAscii().data() << endl;
}
#include "myunit.h"
#include <iostream>
#include <QtNetwork>
#include <QDebug> // TODO remove in production!
using namespace std;
extern QString getDateTime();
extern char * toCharP ( QString str );
myUnit::myUnit ( int socketDescriptor, Server *parent ) : QThread ( parent )
{
// initialize the unit's socket --> provided by Server::incomingConnection()
if ( !tcpSocket.setSocketDescriptor ( socketDescriptor ) )
{
emit error ( tcpSocket.error() );
return;
}
// this unit doesn't have an IMEI yet...
gotImei=false;
// initialize our imei (000000000000000)
strcpy(imei, "00000000000000");
// access to this parent server object
server=parent;
connect ( &tcpSocket, SIGNAL ( readyRead() ), this, SLOT ( incomingData() ) );
connect ( &tcpSocket, SIGNAL ( disconnected() ), this, SLOT ( disconnected() ) );
}
/**
* myUnit::~myUnit()
* Reimplementation of the QThread's destructor.
* Just to exhibit a message upon this client disconnection.
*/
myUnit::~myUnit()
{
char * dt = toCharP ( getDateTime() );
cout << dt << ": Unit [" << imei << "] disconnected." << " # active clients: " << server->nbrClients << endl;
}
/**
* void myUnit::run()
* Reimplementation of QThread::run().
* Just to exhibit a message upon a new client connection.
* The exec() begins a loop for the thread's events.
*/
void myUnit::run()
{
char * dt = toCharP ( getDateTime() );
peerAddress = toCharP ( tcpSocket.peerAddress().toString() );
cout << dt << ": Incoming connection from [" << peerAddress << "]" << " # clients: " << server->nbrClients << endl;
exec();
}
/**
* void myUnit::disconnected ();
* This function (slot) is connected to the tcpSocket disconnected() signal.
* Decrements the parent server object nbrClients member and exits the thread.
* The quit() insures a graceful exit from the thread, cleaning up child objects and associated memory.
*/
void myUnit::disconnected()
{
server->nbrClients--;
this->quit();
}
/**
* void myUnit::incomingData ();
* This function (slot) is connected to the tcpSocket readyRead() signal, so that when any data is available
* on the socket it's thrown here.
* returns the number of bytes read.
*/
void myUnit::incomingData ()
{
QByteArray unitData;
unitData=tcpSocket.readAll();
int nbrBytes = unitData.length();
cout << "Incoming data from [" << peerAddress << "] - Nbr. of bytes: " << nbrBytes;
if (!gotImei) {
cout << " - checking IMEI..." << endl;
checkImei(unitData);
}
else {
cout << " - parsing data..." << endl;
}
}
quint64 myUnit::writeData ()
{
// TODO
return 0;
}
void myUnit::checkImei (QByteArray &bData)
{
QString sData(bData);
unsigned int nBytes = sData.left(2).toUInt();
cout << "nBytes: " << nBytes << endl;
cout << "sData: " << sData.right(15).toAscii().data() << endl;
}
To copy to clipboard, switch view to plain text mode
As you can see I'm even converting the QByteArray into a QString in checkImei...
Only if I assign sData=bData.right(15).toAscii().data() right off will I get the Imei... I'm aware that this is expected behavior since QString data is \0 terminated and the first 2 bytes of dData contain a \0 byte value.
So I wonder... If my devices output everything in binary,16bit values, how do I write a function to extract the data coming in that socket?!
:frustrated:
Please help using the above code so that I can get out of this and start focusing on the real implementation...
(I really don't want to go back to PHP...)
Thanks in advance,
Pedro Doria Meunier.
Bookmarks