PDA

View Full Version : Problem with QTcpSockets and QVector



Krieger910
26th March 2012, 13:38
Hello i am just writing a computer Game , called BattleShips. It's just a computer game with a client,server,client communication where the main communication is just throw a QVector and QTcpsockets,and i am sending these QVectors with an overloaded Function.


This is the Function where i send my QVector to the Server.


void Client::sendPlayground(){

// QByteArray wird definiert
QByteArray block;
// QDataStream zum Schreiben in das QByteArray
QDataStream out(&block, QIODevice::WriteOnly);
// Version des DataStereams setzen
out.setVersion(QDataStream::Qt_4_5);
// Daten in den Stream schreiben
out << qint16(0)
<< qint8('P')
<< *m_playground;

// Zurueckspulen und
out.device()->seek(0);
// Datenlaenge in Byte schreiben

qint16 blocksize=qint16(block.size() - sizeof(qint16));
qDebug() << "Size of mine Playground " << sizeof(*m_playground);
qDebug() << "Size of Vector 1"<< sizeof(m_playground->m_defArea->getVector());
qDebug() << "Size of Vector 1"<< sizeof(m_playground->m_offArea->getVector());

qDebug() << "Blocksize Playground Client" << blocksize << "Size of DataStream" << block.size();
out << blocksize;

// QByteArray an den Client schicken
m_serverConnection->write(block);
m_serverConnection->flush();

}

Here is my function for overloading my object called Playground , Playground inherits two Objects called GameArea also stores one QVectors for saving some stats.

Serialize


QDataStream& operator <<(QDataStream & os,const Playground& pg ){

os << pg.m_defArea->getSize() << pg.m_defArea->getVector() << pg.m_offArea->getSize() << pg.m_offArea->getVector();

return os;

}



//Deserialize

QDataStream& operator>>(QDataStream & is,Playground& pg ){



QVector<QVector<int> > vec1;

QSize size1;



QVector<QVector<int> > vec2;

QSize size2;



is >> size1 >> vec2 >> size2 >> vec1;





pg.m_offArea->setSize(size1);

pg.m_offArea->setVector(vec1);



qDebug() << "Size 1" << size1;

qDebug() << "Size 2" << size2;



pg.m_defArea->setSize(size1);

pg.m_defArea->setVector(vec2);



return is;



}

and here is my GameArea , this Objects stores a QVector<QVector<int> > m_cells which saves some stats.


#ifndef GAMEAREA_H
#define GAMEAREA_H

#include <QWidget>
#include <vector>
#include <QMouseEvent>
#include "Game.h"
#include <QDebug>
#include <QVector>
#include <QMap>
#include <QObject>


class Client;

class GameArea : public QWidget
{
Q_OBJECT
public:
GameArea(Client* client);
~GameArea();
//KopyConstructor
GameArea(const GameArea &a);
GameArea& operator=(const GameArea&a);

void setCellState(int x,int y, int value);
int getCellState(int x, int y);
bool isCellEmpty(int x, int y);
void setlocked(bool flag);
void clear();
void setShipMode(Shiptype type);
Shiptype getShipMode();
bool createShip(int x, int y);
void loadResources();

//Returns the stored Vector
const QVector<QVector<int> >& getVector() const;
//Returns the size of the Vector
QSize getSize() const;

//sets the new Vector
void setVector(QVector<QVector<int> > vec);
//sets new Size
void setSize(const QSize& size);

void count_ships();//Hits and Fails in the GameArea for Enemy and You

//Get my count ships
QMap<char,int> * get_m_c_ships();

//Get all maximum of all Ships
QMap<char,int> * get_m_m_ships();

//Get my hits and fails
QMap<char,int> * get_m_hit_fails();

//Get hits and fails of the enemy
QMap<char,int> * get_e_hit_fails();

bool isReady();

signals:
void new_Move();
void won();
void lost();

protected:
virtual void paintEvent(QPaintEvent *e);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
void getRectForCell(int x, int y, QRect& rect);

private:
QPoint m_tagged;
int m_width;
int m_height;
int m_offsetX; // width-offset from margin
int m_offsetY; // height-offset from margin
QVector<QVector<int> > m_cells;
void reserve_m_cells(int rows,int col);
void resize_m_cells(int rows,int col);

bool isInitialized;
bool m_locked;
Client* m_client;
Shiptype m_shipType;
QImage* image;

QMap<char,int> m_c_ships;
QMap<char,int> m_m_ships;


QMap<char,int> m_hit_fails;
QMap<char,int> e_hit_fails;

};

Q_DECLARE_TYPEINFO(GameArea, Q_MOVABLE_TYPE );
Q_DECLARE_TYPEINFO(QVector<QVector<int> >, Q_MOVABLE_TYPE );

#endif // GAMEAREA_H

Here is my function to get this QVector from my Object


const QVector<QVector<int> >& GameArea::getVector() const{


return m_cells;

}



I don't know where the problem is , it's possible to exchange this QVectors via QDataStream andQTcpSockets but after some time after relogging both to the QTcpServer,the size of the QDataStream just increased and is increasing,i don't know is it a memory leak or a problem with the QVector and writing it into the QDataStream.It's possible to play against another without any problems but after ending the session and relogging to the QTcpServer this failure occures.
It's a new session,in a new thread of the server.


With best regards Mark

wysota
26th March 2012, 14:39
What does the code for receiving data over network look like?

Krieger910
26th March 2012, 20:48
Here is it from the QTcpServer, one function for one socket , just sychronised in the run methode , i know that the QTcpSocket has an internal buffer which is limited , but this is no the main problem.


bool ServerThread::readData_1(){
// QDataSteram aus TcpSocket erzeugen
QDataStream in(m_client_Connection_1);
in.setVersion(QDataStream::Qt_4_5);
qint16 blocksize=0;
qint8 ch;

qDebug() << "Size Packet Client 1" << m_client_Connection_1->size();

// versuche Blockgroesse zu lesen
if (m_client_Connection_1->bytesAvailable() < (int)sizeof(qint16)) {
// keine Daten vorhanden
qDebug() << "Blocksize 1 false";
return false;
}
in >> blocksize;


// versuche Daten zu lesen
if (m_client_Connection_1->bytesAvailable() < blocksize) {
// Daten in Blockgroesse nicht vorhanden
qDebug() << "Blocksize 1 false " <<"Blocksize" << blocksize << "Size" << m_client_Connection_1->size();
return false;
}

in >> ch;

qDebug() << (char)ch;

//Player 1 give up //Player 2 won
if(ch == 'Q'){
qDebug() << "Client 1 Quit" ;
client_1_has_left=true;
client_sendData_Q(m_client_Connection_2);
client_sendData_L(m_client_Connection_2);
m_client_Connection_2->waitForBytesWritten(10);
m_client_Connection_1->close();
m_client_Connection_2->close();
this->quit();
return false;
}
//Name
if(ch == 'N'){
readName(in);
return true;
}
//Ready
if(ch == 'R' ){
this->client_1_isready=true;
qDebug() << "Client 1 is ready ";
return true;
}
if(ch == 'L'){
qDebug() << "Client 1 got Won Signal";
client_sendData_L(m_client_Connection_2);
return true;
}
if(ch == 'P'){

QVector<QVector<int> > vec1;
QSize size1;

QVector<QVector<int> > vec2;
QSize size2;

in >> size1 >> vec1 >> size2 >> vec2;

client_sendData_P(m_client_Connection_2,vec1,size1 ,vec2,size2);

vec1.clear();
vec2.clear();

if(m_client_Connection_1->size() > 0){
readData_1();

}

return true;
}

return false;

}

Here is the main problem at client, in the function send_playground(),i just did an screen shot of my console and the during the first game the size of my stream has not changed,but after relogging to the server the size of my stream which is send in the function send_playground has changed from 4377 to 10905, so why is it , during the last game and the next game the size has not changed of my object(m_playground) or the Vectors which are stored in it,but the size of my stream which is send throw the socket to server has changed.



7532

so the datasize has just increased(QDataStream),but (perhaps) not the size of my objects

wysota
26th March 2012, 21:08
What is the type of m_client_Connection_1? It looks like you are trying to read 16 bits of data each time the function is called which corrupts your stream if there is not enough data to read after you already know the block size. Then you seem to be completely ignoring the block size you just read and you start reading from the stream regardless if there is enough data available or not.

Krieger910
27th March 2012, 09:54
Yeah it's true , that i am not looking if there is enough space or not,but in the beginning 16 bits of data are just enough to communicate there is no problem ,that the size of my stream is not enough,the communication between my clients and servers works.But afterwards the size of stream has changed, and i don't know why.

Here is a picture,that u know how my games looks like , there is a grid and the status are stored in an QVector<QVector<int> > m_cells, and the size of my grid hasn't changed during playing so also the size of my vectors but the size of my stream has changed after relogging and maybe it's getting more and more,i am also looking if the stream is clear or not at the clients and at the server during starting and stopping the session.
7533

wysota
27th March 2012, 11:11
Yeah it's true , that i am not looking if there is enough space or not,but in the beginning 16 bits of data are just enough to communicate there is no problem ,that the size of my stream is not enough,the communication between my clients and servers works. But afterwards the size of stream has changed, and i don't know why.

You are losing sync with your protocol (which is QDataStream). You get bogus data and you misinterpret it. You need to redesign how your communication looks like, taking into consideration the nature of TCP which is often forgotten by people. You can't neglect properties of a protocol when trying to use it. If your stream contains 1000 messages, you will only read the first one. That's one of the possibilities why your stream changes its size.