PDA

View Full Version : duplicate data on TCPSocket



daemonna
2nd August 2010, 10:57
i'm getting duplicate data on client-server communication... when sending for example 65502 (hex ffde), on socket i can see duplicate (ffdeffde..)..

to client.. wanna auth? client wanna authenticate???
question 67 op 1 67 = -122
"ffdeffde434301"
getting auth answer from client... checking


asking for authentication??? writing authme
sending auth question??? "ffdeffde4343010032000000010000000a000500e0010c00e8 e83d0010e83d0010e83d0010e83d0"
writing autha
auth passed


SERVER:


QByteArray auth;
QDataStream dsauth(&auth,QIODevice::ReadWrite);
....etc

indg_socket::indg_socket(QObject *parent) :
QTcpSocket(parent)
{
//generate random numbers
srand(time(NULL));
random1=rand()%256;
//sleep(3);
srand(time(NULL));
random2=rand()%256;
srand((time(NULL)+5));
oper=rand()%5;

result=computeauth(random1, random2, oper); //put 2 random numbers, random operation and compute result


dsauth << (quint16)65500;
dsauthme << (quint16)65501;
dsauthq << (quint16)65502;
dsautha << (quint16)65503;
dsuserkeys << (quint16)65504;
dsauthok << (quint16)65508;
dsauthfailure << (quint16)65509;
dsadmstatq << (quint16)65510;

isClientAuthenticated=false;
connect(this, SIGNAL(readyRead()), this, SLOT(readpackets()));
connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
}

void indg_socket::readpackets()
{
sockdata=this->readAll();
sockdata.truncate(100); //truncate if packet greater than 100 bytes

if(sockdata==authme){
qDebug() << "client wanna authenticate!!!";
qDebug() << "sending question " << random1 << " op" << oper << " " << random2 << " = " << result;
authq.clear();
dsauthq << (quint16)65502 << (quint8)random1 << (quint8)random2 << (quint8)oper;
qDebug() << authq.toHex();
this->write(authq, 40);
sockdata.clear();
return;
}

if(sockdata==autha){
qDebug() << "getting auth answer from client... checking";
qDebug() << "OK";
this->write(authok);
sockdata.clear();
return;
}

if(sockdata.startsWith(admstatq)){
qDebug() << "getting auth answer from client... checking";
qDebug() << "OK";
this->write(authok);
sockdata.clear();
return;
}

return;
}

CLIENT:


ait_socket::ait_socket(QObject *parent) :
QTcpSocket(parent)
{
dsauth << (quint16)65500;
dsauthme << (quint16)65501;
dsauthq << (quint16)65502;
dsautha << (quint16)65503;
dsuserkeys << (quint16)65504;
dsauthok << (quint16)65508;
dsauthfailure << (quint16)65509;

connect(this, SIGNAL(readyRead()), this, SLOT(readpackets()));
connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
}

void ait_socket::readpackets()
{
sockdata=this->readAll();

if(sockdata.startsWith(auth)){
qDebug() << "server asking for authentication!!!";
qDebug() << "OK, writing authme";
this->write(authme);
sockdata.clear();
return;
}

if(sockdata.startsWith(authq)){
qDebug() << "server sending auth question!!!";
qDebug() << sockdata.toHex();
qDebug() << "OK, writing autha";
this->write(autha);
sockdata.clear();
return;
}

if(sockdata.startsWith(authok)){
qDebug() << "auth passed!";
this->write(userkeys);
sockdata.clear();
return;
}
return;
}

daemonna
2nd August 2010, 10:59
i bet the problem is with my code, but after few days lookin at it, i didnt find problem... so PLEASE any help is really appreciated.

thanx in advance

tbscope
2nd August 2010, 11:21
The code isn't easy to follow and it contains variables I don't see defined, like authq

You you edit the code to include the complete header and implementation of the client and server?
And canu place the code between code tags. It's the # icon in the toolbar.

daemonna
2nd August 2010, 11:38
Header:

#ifndef INDG_SOCKET_H
#define INDG_SOCKET_H

#include <QTcpSocket>
#include <QtGlobal>

class indg_socket : public QTcpSocket
{
Q_OBJECT
public:
explicit indg_socket(QObject *parent = 0);
qint32 computeauth(qint32 random1, qint32 random2, qint32 oper);

protected:
void readyRead();

private slots:
void readpackets();
};

#endif // INDG_SOCKET_H

CPP:

#include "indg_socket.h"

#include <QtNetwork>
#include <QtDebug>
#include <QByteArray>
#include <QtGlobal>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

bool isClientAuthenticated;
qint32 random1;
qint32 random2;
qint32 oper;
qint32 result;

QByteArray auth; //65500 do you want to authenticate?
QByteArray authme; //65501 authenticate me
QByteArray authq; //65502 auth question for client
QByteArray autha; //65503 auth answer for server
QByteArray userkeys;//65504 i'm sending user keys
QByteArray wmp; //65505 whole map for client
QByteArray partd; //65506 partial data for client

QByteArray authok; //65508 auth OK
QByteArray authfailure; //65508 auth FAILED
QByteArray admstat; //65509 admin stats
QByteArray admstatq; //65510 admin stats query

QByteArray sockdata;
QDataStream dsauth(&auth,QIODevice::ReadWrite);
QDataStream dsauthme(&authme,QIODevice::ReadWrite);
QDataStream dsauthq(&authq,QIODevice::ReadWrite);
QDataStream dsautha(&autha,QIODevice::ReadWrite);
QDataStream dsuserkeys(&userkeys,QIODevice::ReadWrite);
QDataStream dswmp(&wmp,QIODevice::ReadWrite);
QDataStream dspartd(&partd,QIODevice::ReadWrite);
QDataStream dsadmstat(&admstat,QIODevice::ReadWrite);
QDataStream dsadmstatq(&admstatq,QIODevice::ReadWrite);

QDataStream dsauthok(&authok,QIODevice::ReadWrite);
QDataStream dsauthfailure(&authfailure,QIODevice::ReadWrite);

indg_socket::indg_socket(QObject *parent) :
QTcpSocket(parent)
{
//generate random numbers
srand(time(NULL));
random1=rand()%256;
//sleep(3);
srand(time(NULL));
random2=rand()%256;
srand((time(NULL)+5));
oper=rand()%5;

result=computeauth(random1, random2, oper);


dsauth << (quint16)65500;
dsauthme << (quint16)65501;
dsauthq << (quint16)65502;
dsautha << (quint16)65503;
dsuserkeys << (quint16)65504;
dsauthok << (quint16)65508;
dsauthfailure << (quint16)65509;
dsadmstatq << (quint16)65510;

isClientAuthenticated=false;
connect(this, SIGNAL(readyRead()), this, SLOT(readpackets()));
connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
}

void indg_socket::readpackets()
{
sockdata=this->readAll();
sockdata.truncate(100); //truncate if packet greater than 100 bytes

if(sockdata==authme){
qDebug() << "client wanna authenticate!!!";
qDebug() << "sending question " << random1 << " op" << oper << " " << random2 << " = " << result;
authq.clear();
dsauthq << (quint16)65502 << (quint8)random1 << (quint8)random2 << (quint8)oper;
qDebug() << authq.toHex();
this->write(authq, 40);
sockdata.clear();
return;
}

if(sockdata==autha){
qDebug() << "getting auth answer from client... checking";
qDebug() << "OK";
this->write(authok);
sockdata.clear();
return;
}

if(sockdata.startsWith(admstatq)){
qDebug() << "getting auth answer from client... checking";
qDebug() << "OK";
this->write(authok);
sockdata.clear();
return;
}

return;
}

qint32 indg_socket::computeauth(qint32 random1, qint32 random2, qint32 oper)
{
qint8 res;
switch(oper){
case 1:
res=random1+random2;
return res;
case 2:
res=random1-random2;
return res;
case 3:
res=random1*random2;
return res;
case 4:
res=random1/random2;
return res;
}
}


client side

#ifndef AIT_SOCKET_H
#define AIT_SOCKET_H

#include <QTcpSocket>

class ait_socket : public QTcpSocket
{
Q_OBJECT
public:
explicit ait_socket(QObject *parent = 0);

protected:
void readyRead();

private slots:
void readpackets();
};

#endif // AIT_SOCKET_H


CPP

#include "ait_socket.h"

#include <QtNetwork>
#include <QtDebug>
#include <QByteArray>
#include <QtGlobal>
#include <stdio.h>

QByteArray auth; //65500 do you want to authenticate?
QByteArray authme; //65501 authenticate me
QByteArray authq; //65502 auth question for client
QByteArray autha; //65503 auth answer for server
QByteArray userkeys;//65504 i'm sending user keys
QByteArray wmp; //65505 whole map for client
QByteArray partd; //65506 partial data for client

QByteArray authok; //65508 auth OK
QByteArray authfailure; //65508 auth FAILED
QByteArray admstat; //65509 admin stats
QByteArray admstatq; //65510 admin stats query

QByteArray sockdata;
QDataStream dsauth(&auth,QIODevice::ReadWrite);
QDataStream dsauthme(&authme,QIODevice::ReadWrite);
QDataStream dsauthq(&authq,QIODevice::ReadWrite);
QDataStream dsautha(&autha,QIODevice::ReadWrite);
QDataStream dsuserkeys(&userkeys,QIODevice::ReadWrite);
QDataStream dswmp(&wmp,QIODevice::ReadWrite);
QDataStream dspartd(&partd,QIODevice::ReadWrite);
QDataStream dsadmstat(&admstat,QIODevice::ReadWrite);

QDataStream dsauthok(&authok,QIODevice::ReadWrite);
QDataStream dsauthfailure(&authfailure,QIODevice::ReadWrite);


ait_socket::ait_socket(QObject *parent) :
QTcpSocket(parent)
{
dsauth << (quint16)65500;
dsauthme << (quint16)65501;
dsauthq << (quint16)65502;
dsautha << (quint16)65503;
dsuserkeys << (quint16)65504;
dsauthok << (quint16)65508;
dsauthfailure << (quint16)65509;

connect(this, SIGNAL(readyRead()), this, SLOT(readpackets()));
connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
}

void ait_socket::readpackets()
{
sockdata=this->readAll();

if(sockdata.startsWith(auth)){
qDebug() << "server asking for authentication!!!";
qDebug() << "OK, writing authme";
this->write(authme);
sockdata.clear();
return;
}

if(sockdata.startsWith(authq)){
qDebug() << "server sending auth question!!!";
qDebug() << sockdata.toHex();
qDebug() << "OK, writing autha";
this->write(autha);
sockdata.clear();
return;
}

if(sockdata.startsWith(authok)){
qDebug() << "auth passed!";
this->write(userkeys);
sockdata.clear();
return;
}
return;
}

daemonna
2nd August 2010, 11:39
btw. dont worry about computeauth() and use of it in communication... this will be fixed as soon as mystery of duplicate data is sorted out...

tbscope
2nd August 2010, 14:18
One problem is this line:


this->write(authq, 40);
This makes an implicite conversion from QByteArray to const char*
For some reason this works, but I'm sure it won't give you what you want.

This might not be the problem why you get things double though.


Another thing that's not 100% correct is the initialisation of your random number generators.

tbscope
2nd August 2010, 14:34
And the probable reason why you get a double auth code is because you don't flush the stream.
You do clear the bytearray though.

Note that this is a pure guess though!

In short: this is what happens

create bytearray authq
create datastream dsauthq which writes and reads on bytearray authq

by default (in the constructor) already write (quint16)65502 via the data stream to the bytearray.
clear the bytearray
The stream still contains the code
Now write the code again with the random numbers and operator.

In effect, you write the code twice.

The fun thing is, QDatastream doesn't have a flush() function.
Delete the stream and create a new one on the go. That will definatly solve stream buffer problems.

I would do this very differently though but I assume you can not change the requirements of (quint16)65502 ?

tbscope
2nd August 2010, 14:45
Confirmation:



#include <QtCore/QCoreApplication>

#include <QDebug>
#include <QByteArray>
#include <QDataStream>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

qint32 random1;
qint32 random2;
qint32 oper;

//generate random numbers
srand(time(NULL));
random1=rand()%256;
//sleep(3);
srand(time(NULL));
random2=rand()%256;
srand((time(NULL)+5));
oper=rand()%5;

qDebug() << "Test hex";
qDebug() << "";

QByteArray array;
QDataStream stream(&array,QIODevice::ReadWrite);

stream << (quint16)65502;
array.clear();
stream << (quint16)65502 << (quint8)random1 << (quint8)random2 << (quint8)oper;

qDebug() << "Hex =" << array.toHex();

QDataStream stream1(&array, QIODevice::ReadWrite);
QDataStream stream2(&array, QIODevice::ReadWrite);

array.clear();
stream1 << (quint16)65502;
array.clear();
stream2 << (quint16)65502 << (quint8)random1 << (quint8)random2 << (quint8)oper;

qDebug() << "Hex =" << array.toHex();

return a.exec();
}




Results:


Test hex

Hex = "ffdeffde5d5d01"
Hex = "ffde5d5d01"



Edit: All I can say is that QDataStream is not meant to be used like this.

daemonna
3rd August 2010, 07:24
thanks for all your replies...


Edit: All I can say is that QDataStream is not meant to be used like this.

what else do you suggest if i need to work with 'raw data', not a text???

daemonna
4th August 2010, 06:29
yeah, you were exactly right.. i had to use separate qbytearray to send thru socket, and mentioned bytearrays use only for comparison (sockdata.startsWith(auth)) + i have to use .device()->seek(0) all the time to make sure nothing left in bytearray, coz i've noticed packet was several times OK, but suddenly i found extra zeros in beginning of array..

THANKS ;)