transfer struct data on udpSocket
hello community,
i am new in this forum and in qt I need your help to finish my program.
i am writing a c++ code with the IDE Qt for my project.
i have two separately classes, that communicate on updsocket. One class(SendObjects) send data on port 50885 and the second class(receiveObjects) receive this data on port 50885. The data to send are of type struct. In both classes i have declared a structure type, called mDataChannels with 6 elements: Channel_Nr, AC_Volt, DC_Volt,etc...
Now on my socket with port 50885 from class "SendObjects", i want to send simultaneously 40 objects of typ structure(mDataChannels) and then receive this all objects(or all elements of this) on the other class names "receiveObjects".
i tried to write a code with and without QVector but it doesn't work fine. I need help to improve my code. i don't have error but i cannot read something. I don't too know if my class "SendObjects" or my class "receiveObjects" really work fine. I have added a new QDataStream Operator. may be it is wrong.
SendObject.h
Code:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QUdpSocket>
#include <QTimer>
#include <QDateTime>
#include <vector>
#include <QString>
#include <QDebug>
#include <QVector>
namespace Ui {
class MainWindow;
}
struct mDataChannels
{
float mAC_Volt;
float mDC_Volt;
float mAC_Current;
float mDC_Current;
float mmPotential;
};
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= 0);
~MainWindow();
friend QDataStream
& operator <<
(QDataStream &stream,
const QVector<mDataChannels>
&_DataTest
);
private slots:
void sendTestData();
private:
Ui::MainWindow *ui;
QVector < mDataChannels > _DataTest, temp;
};
#endif // MAINWINDOW_H
,
SendObject.cpp
Code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
_DataTest.resize(40);
temp.resize(40);
for(int i = 0; i < 40; i++)
{
_DataTest
[i
].
mmyChannel_Nr = tr
("Kanal ") +QString::number(i
+ 1);
_DataTest[i].mAC_Volt = 150.320 + (float)i;
_DataTest[i].mDC_Volt = 80.67 + (float)i;
_DataTest[i].mAC_Current = 5.0 + (float)i/10;
_DataTest[i].mDC_Current = 3.0 + (float)i/10;
_DataTest[i].mmPotential = 6.0 + (float)i/2;
}
connect(testTimer, SIGNAL(timeout()), this, SLOT(sendTestData()));
testTimer->start(2 * 1000);
}
MainWindow::~MainWindow()
{
delete ui;
}
QDataStream
& operator <<
(QDataStream &stream, QVector<mDataChannels>
&_DataTest
){
_DataTest.resize(40);
stream << dataTime;
for(int i = 0; i < 40; i++)
stream <<
(QString)_DataTest
[i
].
mmyChannel_Nr << static_cast<float>
(_DataTest
[i
].
mAC_Volt) << static_cast<float>(_DataTest[i].mDC_Volt) << static_cast<float>(_DataTest[i].mAC_Current)
<< static_cast<float>(_DataTest[i].mDC_Current) << static_cast<float>(_DataTest[i].mmPotential);
return stream;
}
void MainWindow::sendTestData()
{
for(int i = 0; i < 40; i++)
stream << _DataTest[i].mmyChannel_Nr << _DataTest[i].mAC_Volt
<< _DataTest[i].mDC_Volt << _DataTest[i].mAC_Current
<< _DataTest[i].mDC_Current << _DataTest[i].mmPotential;
testUdpSocket
->writeDatagram
(myTestSendData,
QHostAddress::LocalHost,
50885);
}
receiveObjects.h
Code:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QUdpSocket>
#include <QTimer>
#include <QDebug>
#include <QDateTime>
namespace Ui {
class MainWindow;
}
struct DataChannels
{
float AC_Volt;
float DC_Volt;
float AC_Current;
float DC_Current;
float mPotential;
};
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= 0);
~MainWindow();
friend QDataStream
& operator >>
(QDataStream &stream,
QVector <DataChannels>
&receivePacket
);
private slots:
void readAllValue();
private:
Ui::MainWindow *ui;
QVector < DataChannels > receivePacket;
};
#endif // MAINWINDOW_H
,
receiveObjects.cpp
Code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
receivePacket.resize(40);
connect(readSocket, SIGNAL(readyRead()), this, SLOT(readAllValue()));
}
MainWindow::~MainWindow()
{
delete ui;
}
QDataStream
& operator >>
(QDataStream &stream, QVector<DataChannels>
&receivePacket
){
quint32 tempInt;
receivePacket.resize(40);
stream >> mDateTime;
for(int i = 0; i < 40; i++)
{
stream >> tempString; receivePacket[i].myChannel_Nr = tempString;
stream >> tempInt; receivePacket[i].AC_Volt = tempInt;
stream >> tempInt; receivePacket[i].DC_Volt = tempInt;
stream >> tempInt; receivePacket[i].AC_Current = tempInt;
stream >> tempInt; receivePacket[i].DC_Current = tempInt;
stream >> tempInt; receivePacket[i].mPotential = tempInt;
}
return stream;
}
void MainWindow::readAllValue()
{
do
{
mReceiveDatagram.resize(int(readSocket->pendingDatagramSize()));
readSocket->readDatagram(mReceiveDatagram.data(), mReceiveDatagram.size());
} while(readSocket->hasPendingDatagrams());
stream >> dateTime;
for(int i = 0; i< 40; i++)
{
stream >> receivePacket[i].myChannel_Nr >> receivePacket[i].AC_Volt >> receivePacket[i].DC_Volt
>> receivePacket[i].AC_Current >> receivePacket[i].DC_Current >> receivePacket[i].mPotential;
}
}
Re: transfer struct data on udpSocket
Re: transfer struct data on udpSocket
Do you have a test, e.g. unittest, that checks for serialization and deserialization without any network involvement?
Do you receive datagrams?
Any reason you discard all datagrams but the last?
Your stream operators aren't used so they can't really be the problem.
If your goal is to use them in a later stage of your program, you should probably rethink using a hard coded magic number (40) when looping :-)
Cheers,
_
Re: transfer struct data on udpSocket
thank you already for your answer,
Quote:
Originally Posted by
anda_skoa
Do you have a test, e.g. unittest, that checks for serialization and deserialization without any network involvement?
_
i don't have. i only started both programs(SendObject and ReceiveObject). Normally , the class sendObject is for serialization of my struct Object and the class ReceiveObject is for deserialization, i th thought so. Maybe it's my code that was badly written.
Quote:
Originally Posted by
anda_skoa
Do you receive datagrams? _
i don't receive anything. i tried to sniff my network with wireshark, something is sent that i cannot read or receive on my Class receiveObject.
Quote:
Originally Posted by
anda_skoa
Any reason you discard all datagrams but the last?_
i want to send all datagrams, that is the goal of my program. i didn't know that i discard all datagrams except the last
Quote:
Originally Posted by
anda_skoa
Your stream operators aren't used so they can't really be the problem._
How to use it?
Quote:
Originally Posted by
anda_skoa
If your goal is to use them in a later stage of your program, you should probably rethink using a hard coded magic number (40) when looping :-)_
i didn't understand what do you mean? normally with my class "sendObject" i want to send 40 object of type struct on the socket. One object of this struct contains 6 elements.
I written a simple program that send only one Object of type struct and receives it. It works fine. i can receive something that i send but i have to send every element of my object of type struct.
So now if i want to send 40 objects of type struct containing each 6 elements, i have to send element by element. That's long. That's why i wanted to integrate a QVector that i cannot send and read.
thank you already for your answer,
Quote:
Originally Posted by
anda_skoa
Do you have a test, e.g. unittest, that checks for serialization and deserialization without any network involvement?
_
i don't have. i only started both programs(SendObject and ReceiveObject). Normally , the class sendObject is for serialization of my struct Object and the class ReceiveObject is for deserialization, i th thought so. Maybe it's my code that was badly written.
Quote:
Originally Posted by
anda_skoa
Do you receive datagrams? _
i don't receive anything. i tried to sniff my network with wireshark, something is sent that i cannot read or receive on my Class receiveObject.
Quote:
Originally Posted by
anda_skoa
Any reason you discard all datagrams but the last?_
i want to send all datagrams, that is the goal of my program. i didn't know that i discard all datagrams except the last
Quote:
Originally Posted by
anda_skoa
Your stream operators aren't used so they can't really be the problem._
How to use it?
Quote:
Originally Posted by
anda_skoa
If your goal is to use them in a later stage of your program, you should probably rethink using a hard coded magic number (40) when looping :-)_
i didn't understand what do you mean? normally with my class "sendObject" i want to send 40 object of type struct on the socket. One object of this struct contains 6 elements.
I written a simple program that send only one Object of type struct and receives it. It works fine. i can receive something that i send but i have to send every element of my object of type struct.
So now if i want to send 40 objects of type struct containing each 6 elements, i have to send element by element. That's long. That's why i wanted to integrate a QVector that i cannot send and read.
Added after 6 minutes:
this is my simple code to send and receice element by element of an object of type struct
send.h
Code:
namespace Ui {
class MainWindow;
}
struct DataChannels
{
float AC_Volt;
float DC_Volt;
float AC_Current;
float DC_Current;
float Potential;
};
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= 0);
~MainWindow();
private slots:
void sendTestData();
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
DataChannels mData, temp;
};
#endif // MAINWINDOW_H
send.cpp
Code:
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
mData.
myChannel_Nr = tr
("Kanal ") +QString::number(1);
mData.AC_Volt = 150.320;
mData.DC_Volt = 80.67;
mData.AC_Current = 5.0;
mData.DC_Current = 3.0;
mData.Potential = 6.0;
temp = mData;
connect(testTimer, SIGNAL(timeout()), this, SLOT(sendTestData()));
testTimer->start(200);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::sendTestData()
{
stream <<
QDateTime::currentDateTime() << mData.
myChannel_Nr << mData.
AC_Volt << mData.DC_Volt << mData.AC_Current << mData.DC_Current << mData.Potential;
testUdpSocket
->writeDatagram
(myTestSendData,
QHostAddress::LocalHost,
50885);
}
void MainWindow::on_pushButton_clicked()
{
}
receive.h
Code:
namespace Ui {
class MainWindow;
}
struct DataChannels
{
float AC_Volt;
float DC_Volt;
float AC_Current;
float DC_Current;
float Potential;
};
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= 0);
~MainWindow();
private slots:
void readAllValue();
private:
Ui::MainWindow *ui;
DataChannels readPacket;
};
#endif // MAINWINDOW_H
receive.cpp
Code:
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(readSocket, SIGNAL(readyRead()), this, SLOT(readAllValue()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::readAllValue()
{
do
{
mReceiveDatagram.resize(int(readSocket->pendingDatagramSize()));
readSocket->readDatagram(mReceiveDatagram.data(), mReceiveDatagram.size());
} while(readSocket->hasPendingDatagrams());
stream >> dateTime >> readPacket.myChannel_Nr >> readPacket.AC_Volt >> readPacket.DC_Volt
>> readPacket.AC_Current >> readPacket.DC_Current >> readPacket.Potential;
}
Re: transfer struct data on udpSocket
Quote:
Originally Posted by
malone
i don't have. i only started both programs(SendObject and ReceiveObject). Normally , the class sendObject is for serialization of my struct Object and the class ReceiveObject is for deserialization, i th thought so. Maybe it's my code that was badly written.
It is always a good idea narrow down a problem by testing different steps separately.
Serialization/deserialization, for example, can be easily tested with a QBuffer instead of a socket.
Quote:
Originally Posted by
malone
i don't receive anything. i tried to sniff my network with wireshark, something is sent that i cannot read or receive on my Class receiveObject.
Well, then you have to debug why that does not happen before concerning yourself if you possibly also have problems in the deserialization code.
If there is no data to read, there is no data to deserialize.
Quote:
Originally Posted by
malone
i want to send all datagrams, that is the goal of my program. i didn't know that i discard all datagrams except the last
You have a loop that reads all available datagrams into a single buffer, each loop iteration overwriting the previously read data.
Thus you end up with only the data of the last datagram.
Quote:
Originally Posted by
malone
How to use it?
By streaming the vector into the stream
Quote:
Originally Posted by
malone
i didn't understand what do you mean? normally with my class "sendObject" i want to send 40 object of type struct on the socket.
The loops use "40" as hard coded value. If the vector is shorter the loop will crash. If the vector is longer, some values won't be sent.
Iterating over a vector by index usually refers to the vector's size or element count.
Sending a vector would then also first send that number so that the receiving side know how many elements to expect.
Quote:
Originally Posted by
malone
I written a simple program that send only one Object of type struct and receives it. It works fine.
Good.
Next step is to see how many bytes get written when you send a full vector of elements and the compare that to the number of bytes received on the other side.
Separately ensure that serialization and deserialization work as a round trip.
Cheers,
_
Re: transfer struct data on udpSocket
Quote:
Next step is to see how many bytes get written when you send a full vector of elements and the compare that to the number of bytes received on the other side.
but the problem is that i don't get sent with QDatagram a full vector of elements. You told me, that when i used a for-loop, i discard all datagrams except the last. Can show me with a simple code example, how i can send a full vector of elements. May be 20 objetc of type struct with 4 elements.
Thank you!
Re: transfer struct data on udpSocket
Quote:
You told me, that when i used a for-loop, i discard all datagrams except the last.
In your first post, in receiveObjects.cpp, the loop starting at line 45 reads one pending datagram each time through the loop, and it stores it into the same datagram instance. This overwrites whatever the previous contents might have been because before reading the datagram, the object gets resized to whatever size is waiting to be read. The result is that the final datagram object only contains the last datagram you read.