I am trying to make a neural network using signal and slot mechanism.
my neural network is not layered so I have a block of hidden neurons that are connected randomly. so I probably have loops in the structure which i like to have them.
the question is when I start to emit signals from my input neurons, the first input neuron sends the signal to first hidden neuron and then i would rather want my program send the second signal to the second hidden neuron. but instead the first hidden neuron which has received its signal starts to emit its own signals and so on. when the first path reaches to the end (output neuron) then first input neuron emits the second signal to its second hidden neuron. this causes a problem which information flow partially. i.e. before a certain neuron recieves all its inputs it sends a signal only based on one input that it recieved. I tried to solve it by adding a counter that let the signal be emitted after all expected signals are recieved which in the case of the loops that I have in the structure it doesn't work. two neurons are waiting for the other one to send its signal then they have the full set of signals.
even i tried to let an empty signal ( valued 0 ) to be passed before all the signals are recieved and have the complete signal be passed after all signals are recieved. this one doesn't work since empty signals are accumulating the counter and it goes out of control.
void Neuron::receiveOutput(const int &senderIndex, const double &senderOutput)
{
this->m_sumOfSignals += m_indexedWeights[senderIndex] * senderOutput;
m_receivedSignals.push_back(senderIndex);
qDebug() << "I am neuron " << this->index() << " and I received a signal from neuron "
<< senderIndex << " valued " << senderOutput;
if(m_receivedSignals.size() == m_indexedWeights.size())
{
m_output = this->activate();
qDebug() << "I have receieved all " << m_receivedSignals.size() << " signals so I send my output as "
<< m_output;
m_sumOfSignals = 0.0;
emit sendOutput(m_index, m_output);
}
if(m_receivedSignals.size() < m_indexedWeights.size())
{
m_output = this->activate();
qDebug() << "so far I have receieved " << m_receivedSignals.size() << " signals so I send my output as "
<< m_output;
emit sendOutput(m_index, 0.0);
}
if(m_receivedSignals.size() > m_indexedWeights.size())
{
qDebug() << "I have receieved " << m_receivedSignals.size() << " signals so I stoped sending signals";
return;
}
}
so my question is how can I control the signals flowing in the network?
Related
I am very new to programming and I am teaching myself. I wrote a application to poll a number of requests from a control unit . I basically continuously send various read commands to the Control unit and read back the response .My program works and i successfully send commands and receive answers . But the reading is very slow ( i have a 100 ms timeout in my code to ensure i get the complete reply )
I have a program for the same control unit that was written by a professional coder in C++ , in his program he polls every 30 ms and i always receive the complete answer in that time frame . I have the same settings 57K baud 8 bits 1 stop bit and no parity . However my QT code takes almost 100 ms to receive the answer.
In my code i read the first 2 bytes ( first byte is the message identifier and second byte is the remainder of the message length) then i read in a loop until the total message length is equal to the message length byte +1 (the +1 is there to include the first byte ) . I am a wits end as to why my code is so slow in QT when i know its know the Hardware that's the limiting factor . The requests are always 3 bytes and the reply varies from 3 to 61 bytes . Please help me to point me to my error. If i remove the timeout i always have short reads . So far i also tried read(all) but with the same result .
Below is the extract from my code where i read the response . The full code is at https://github.com/MarkusIppy/PowerTune
//Error handling
QTime startTime = QTime::currentTime();
int timeOut = 100; // timeout in milisec.
QByteArray recvData = m_serialport->read(2); // reading first two bytes of received message to determine lenght of ecpected message
int msgLen = recvData[1]; //Total message Lenght excluding the first byte
while ( recvData.size() <= (msgLen+1) )
{
if ( startTime.msecsTo(QTime::currentTime()) > timeOut ) break;
recvData += m_serialport->read(msgLen+1-recvData.size());
}
if (msgLen +1 == recvData.length()) //if the received data lenght equals the message lenght from lenght byte + identifier byte (correct message lenght received )
{
qDebug() << "Received data OK"<<msgLen +1;
if(requestIndex <= 61){requestIndex++;}
else{requestIndex = 58;}
readData(recvData);
}
else //if the lenght of the received message does not correspond with the expected lenght repeat the request
{
qDebug() << "Received data lenght NIO";
readData(recvData);
qDebug() << "Request Message again"<< requestIndex;
}
I am sorry, I don't have enough time to go through your project and from the code you've provided I cannot be 100% sure what the cause is. My best guess though is that the problem in this case is that you wait explicitly for the data to be received and the events processing is somehow delayed or does not take place at all.
Anyway, here you have a couple of suggestions:
Use QTimer for timeouts instead of QTime.
Learn about the Qt5's signals and slots and use them to read from the serial port asynchronously.
I use the QSerialPort by connecting its bytesWritten(qint64 bytes) and readyRead() signals to slots of my program, let's say on_bytesWritten(qint64 bytes) and on_readyRead(). Then I send request to the target device and in the on_readyRead() slot I process the result. With each send command I start a QTimer with its timeout() signal connected to a on_timeout() slot of my application. This way I could monitor whether the device responds in time or not, as well as to have the data as soon as it comes. You may also use the errorOccurred(QSerialPort::SerialPortError error) signal of the QSerialPort to check if there is a problem with the transmission.
Changed my code slightly again and now it works perfectly on the actual Hardware
Below is my ready to read Slot :
void Serial::readyToRead()
{
qDebug() << "ready read";
if(ecu == 0)
{
m_readData.append(m_serialport->readAll());
Bytesexpected = m_readData[1]+1;
qDebug() << "readdata current" <<m_readData.toHex();
if (Bytesexpected == m_readData.size())
{
m_timer.stop();
if(requestIndex <= 62){requestIndex++;}
else{requestIndex = 59;}
readData(m_readData);
Serial::clear();
m_readData.clear();
Serial::sendRequest(requestIndex);
}
if (Bytesexpected != m_readData.size())
{
qDebug() << "starting timer";
m_timer.start(5000);
}
}
This is what i have so far ( just posting the important parts of my cpp file )
This code works now almost perfectly with my message emulator. It polls now as expected but the timeout gets always triggered after 5 seconds ( i need to change it to only trigger if there is no message comming ) . I will only be able to test it on the actual hardware end of next week .
This is what i have so far :
void Serial::initSerialPort()
{
if (m_serialport)
delete m_serialport;
m_serialport = new SerialPort(this);
connect(this->m_serialport,SIGNAL(readyRead()),this,SLOT(readyToRead()));
connect(m_serialport, static_cast<void (QSerialPort::*) (QSerialPort::SerialPortError)>(&QSerialPort::error),
this, &Serial::handleError);
connect(&m_timer, &QTimer::timeout, this, &Serial::handleTimeout);
m_timer.start(5000);
}
void Serial::readyToRead()
{
if(ecu == 0)
{
m_readData.append(m_serialport->readAll());
Bytesexpected = m_readData[1]+1;
if (Bytesexpected == m_readData.size())
{
if(requestIndex <= 62){requestIndex++;}
else{requestIndex = 59;}
readData(m_readData); // message for processing
Serial::clear();
m_readData.clear();
}
//Timeout
if (!m_timer.isActive())
m_timer.start(5000);
}
}
void Serial::handleTimeout()
{
qDebug() << "Timeout";
//request Data Again
QString fileName = "Errors.txt";
QFile mFile(fileName);
if(!mFile.open(QFile::Append | QFile::Text)){
qDebug() << "Could not open file for writing";
}
QTextStream out(&mFile);
out << "Timeout Request Index " << int(requestIndex)<< " lenght received "<< int(m_readData.length())<< " Bytes "<< " Expected Bytes "<< int(Bytesexpected)<< " bytes " <<" Message "<< QByteArray(m_readData.toHex()) <<endl;
mFile.close();
Serial::clear();
m_readData.clear();
Serial::sendRequest(requestIndex);
}
void Serial::handleError(QSerialPort::SerialPortError serialPortError)
{
if (serialPortError == QSerialPort::ReadError) {
QString fileName = "Errors.txt";
QFile mFile(fileName);
if(!mFile.open(QFile::Append | QFile::Text)){
qDebug() << "Could not open file for writing";
}
QTextStream out(&mFile);
out << "Serial Error " << (m_serialport->errorString()) <<endl;
mFile.close();
qDebug() <<"Serialport Error" <<(m_serialport->errorString());
}
}
I am creating a script in QT for reading the format packages (AA), (BB), etc from serial port. I open the serial port, but when I go to check inside the QByteArray values, comes back that I could not read any value.
This is my code
...
QSerialPort *serialPort = new QSerialPort();
serialPort->setPortName("ttyUSB0");
serialPort->setParity(QSerialPort::NoParity);
serialPort->setBaudRate(QSerialPort::Baud9600, QSerialPort::AllDirections);
serialPort->setStopBits(QSerialPort::OneStop);
serialPort->setFlowControl(QSerialPort::NoFlowControl);
serialPort->open(QIODevice::ReadOnly);
if (serialPort->isOpen()) {
qDebug() << "Serial port is open...";
QByteArray datas = serialPort->readAll();
if (datas.size() == 0) {
qDebug() << "Arrived data: 0";
} else {
for (int i = 0; i < datas.size(); i++){
if (datas.at(i)) {
qDebug() << datas[i];
}
}
}
} else {
qDebug() << "OPEN ERROR: " << serialPort->errorString();
}
serialPort->close();
qDebug() << "...serial port is closed!";
return 0;
...
You called readAll() immediately after open(). It probably took the computer a few nanoseconds to get from one to the other.
At 9600 baud, each byte of data takes slightly more than one millisecond to transfer. It would be absolutely impossible for any data to have arrived in that short an interval, so that's why you got no data.
Serial ports don't begin buffering incoming data until you open them (how could they, what baud rate and other settings would be used for receiving and buffering when no program has the port open?)
Use either a blocking read function of some sort (such as readLine()) or an event loop that reacts to data when it arrives.
I tried to create simple server like in link 1.
Youtube tutorial to create multithreaded server
void Test_Server::incomingConnection(int socketDescriptor_)
{
qDebug() << socketDescriptor_ << "connecting...";
Test_Thread *thread_ = new Test_Thread(number_,socketDescriptor_,this);
connect(thread_,SIGNAL(finished()),thread_,SLOT(deleteLater()));
thread_->start();
number_++;
}
////
void Test_Thread::run()
{
qDebug() << this->Socket_Descriptor_ << "starting thread";
socket = new QTcpSocket();
if(!socket->setSocketDescriptor(Socket_Descriptor_))
{
qDebug() << "ERROR";
}
connect(socket,SIGNAL(readyRead()),this,SLOT(Ready_read_()),Qt::DirectConnection);
connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected_()),Qt::DirectConnection);
qDebug() << this->Socket_Descriptor_ << "Client connected";
QByteArray name = QByteArray::number(number_);
server_->Socket_map_.insert(name,this);
server_->show_all_connected_sockets_();
exec();
}
My goal is to connect two clients to server(i use telnet), write from Client 1 to server something, and server should pass data to Client 2.
To do that I've made QMap to storage pointers to MyThreads. When data is received from Client 1, I'm calling method:
void Test_Server::write_to_client_(int number, QByteArray data)
{
QByteArray name = QByteArray::number(number);
Test_Thread *pointer;
pointer = client_socket_(name);
connect(this,SIGNAL(send_data_(QByteArray)),pointer,SLOT(write_data_(QByteArray)));
emit send_data_(data);
disconnect(this,SIGNAL(send_data_(QByteArray)),pointer,SLOT(write_data_(QByteArray)));
qDebug() << "void Test_Server::write_to_client_(int number, QByteArray data): data sent";
}
////
void Test_Thread::write_data_(QByteArray data) const
{
socket->write(data);
socket->waitForBytesWritten();
}
Generally passing information works, I write in Client 1 some data, and Client 2 shows it, however I'm geting:
TQObject: Cannot create children for a parent that is in a different
thread.
Parent Test_Thread is QNativeSocketEngine(Pointer 1), parent's thread is >(Pointer 2), current thread is (Pointer 3);
QsocketNotifier: Socket notifiers cannot be enabled or disabled from another thread.
My question is: how to correctly pass data from client 1, to server, and then to client 2? I've done reasearch and problem lies in proper use of Signals and Slots but I cannot find out how to do it in proper way.
Test_Thread::write_data is not running on the same thread where the socket was created, that is Test_Thread::run(). In the QThread class, only what runs on the run method runs on a separate thread.
I finally solved issue. To do that i followed similar issue solution described here: PROBLEM & SOLUTION
I've resigned to use class MyThread, instead created class Worker and moved it to thread like here below:
void Test_Server::incomingConnection(int socketDescriptor_)
{
qDebug() << "void Test_Server::incomingConnection current thread: " << QThread::currentThread();
qDebug() << socketDescriptor_ << "connecting...";
Socket_map_.insert(number_,QByteArray::number(socketDescriptor_));
QThread *thread_= new QThread;
qDebug() << "void Test_Server::incomingConnection new thread_: " << thread_->thread();
Test_Worker *worker = new Test_Worker(socketDescriptor_);
worker->moveToThread(thread_);
connect(thread_,SIGNAL(started()),worker,SLOT(create_socket_()));
connect(this,SIGNAL(pass_socket_descriptor_(int)),worker,SLOT(set_socket_descriptor_(int)));
connect(worker,SIGNAL(finished()),thread_,SLOT(quit()));
connect(worker,SIGNAL(finished()),worker,SLOT(deleteLater()));
connect(thread_,SIGNAL(finished()),thread_,SLOT(deleteLater()));
connect(worker,SIGNAL(pass_data_to_server_(QByteArray,QByteArray)),this,SLOT(data_from_socket_(QByteArray,QByteArray)));
connect(this,SIGNAL(pass_data_to_client_(QByteArray,QByteArray)),worker,SLOT(show_data_received_from_server_(QByteArray,QByteArray)));
number_++;
thread_->start();
}
HINT: When i created socket via test_server signal create_socket_(int)
and socket create_socket(int), program didn't work correctly. To fix
that connect signal from starting thread to socket - create_socket_
Program now succesfuly without errors receive data from client 1 and pass it to client 2.
So my task is this - I have a GUI thread with sliders of HSV values (among other things), and a worker thread that does all the OpenCV work and sends processed video images back to GUI thread.
Like it usually is, the OpenCV work is inside of an endless loop. The thing is, half the work is transforming the current video frame according to HSV values sent from GUI sliders. If sent before the loop starts, it works. But not while it's going on, and I need it to work on the fly.
Is there any good way to communicate with that thread and change the HSV values the OpenCV loop is using, or is it a fool's errand? I can think of two solutions, one of which is probably highly inefficient (involves saving values to a file). I'm fairly new to Qt, and I could've easly missed something in the documentation and tutorials.
edit:
Here's how my app works - in GUI thread, user picks a file. A signal with an url is sent to the worker thread, which starts working away. When the user changes HSV values, a signal is sent to change the values from another thread. If the loop hasn't been started, they're received and QDebug shows me that.
edit2:
I might've been thinking about it all wrong. Is there a way for the thread to pull values from the other one? Instead of waiting for them to be sent?
edit3:
kalibracja.cpp, for Micka.
int hueMin=0;
int hueMax=180;
int satMin=0;
int satMax=255;
int valMin=15;
int valMax=255;
int satMinDua=133; //tests
HSV::HSV(QObject * parent) : QObject(parent)
{
hsvThread = new QThread;
hsvThread ->start();
moveToThread( hsvThread );
}
HSV::~HSV() //destruktor
{
hsvThread ->exit(0);
hsvThread ->wait();
delete hsvThread ;
}
void HSV::processFrames(QString kalibracja) {
while(1) {
cv::VideoCapture kalibrowanyPlik;
kalibrowanyPlik.open(kalibracja.toStdString());
int maxFrames = kalibrowanyPlik.get(CV_CAP_PROP_FRAME_COUNT);
for(int i=0; i<maxFrames; i++)
{
cv::Mat frame;
cv::Mat gray;
//satMin=kontenerHsv->satMin;
qDebug() << "kalibracja satMin - " << satMin;
qDebug() << "fdfdf - " << satMinDua;
kalibrowanyPlik.read(frame);
cv::cvtColor(frame, gray, CV_BGR2GRAY);
QImage image(cvMatToQImage(frame));
QImage processedImage(cvMatToQImage(gray));
emit progressChanged(image, processedImage);
QThread::msleep(750); //so I can read qDebug() messages easly
}
}
}
void MainWindow::onProgressChagned(QImage image, QImage processedImage) {
QPixmap processed = QPixmap::fromImage(processedImage);
processed = processed.scaledToHeight(379);
ui->labelHsv->clear();
ui->labelHsv->setPixmap(processed);
QPixmap original = QPixmap::fromImage(image);
original = original.scaledToHeight(379);
ui->labelKalibracja->clear();
ui->labelKalibracja->setPixmap(original);
}
void HSV::updateHsv(QString hmin, QString hmax, QString smin, QString smax, QString vmin, QString vmax){
satMinDua=smin.toInt();
}
mainwindow.cpp connection
HSV *hsv = new HSV;
(.... all kinds of things ....)
void MainWindow::updateHsvValues() {
QMetaObject::invokeMethod(hsv, "updateHsv", Qt::QueuedConnection,
Q_ARG(QString, hmin),
Q_ARG(QString, hmax),
Q_ARG(QString, smin),
Q_ARG(QString, smax),
Q_ARG(QString, vmin),
Q_ARG(QString, vmax));
}
It is certainly possible, but you need to be careful.
One of the ways to achieve this would be:
Create an object that stores the "current" HSV values to be used
Give a reference (or pointer) to this object to both the GUI thread and the OpenCV thread
When the GUI wants to "tell" the processing thread to use new values, it published them to that object
When the processing thread is ready to move on the the next frame (start of loop body), it fetches the values from that object.
You only need to make sure that the set and get methods on that shared object are synchronized, using a mutex for example, to prevent the processing thread from reading half-written values (data races lead to undefined behavior in C++).
If you use QThread in the "wrong" way (by subclassing QThread and using ::run , compare to https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ ), signal-slot parameter change works in endless loops too:
This is a small sample thread for testing:
void MyThread::run()
{
// start an infinite loop and test whether the sliderchange changes my used parameters
std::cout << "start infinite loop" << std::endl;
while(true)
{
unsigned long long bigVal = 0;
int lastVal = mValue;
std::cout << "start internal processing loop " << std::endl;
for(unsigned long long i=0; i<1000000000; ++i)
{
bigVal += mValue;
if(lastVal != mValue)
{
std::cout << "changed value: " << mValue << std::endl;
lastVal = mValue;
}
}
std::cout << "end internal processing loop: " << bigVal << std::endl;
}
std::cout << "stop infinite loop" << std::endl;
}
with this SLOT, which is connected to the main window slider SIGNAL
void MyThread::changeValue(int newVal)
{
// change a paramter. This is a slot which will be called by a signal.
// TODO: make this call thread-safe, e.g. by atomic operations, mutual exclusions, RW-Lock, producer-consumer etc...
std::cout << "change value: " << newVal << std::endl;
mValue = newVal;
}
giving me this result after using the slider:
this is how the slot was connected:
QObject::connect(mSlider, SIGNAL(valueChanged(int)), mTestThread, SLOT(changeValue(int)) );
if the infinite loop is performed as some kind of workerObject method which was moved to the thread with moveToThread, you can either change the way how the slot is called:
QObject::connect(mSlider, SIGNAL(valueChanged(int)), mTestThread, SLOT(changeValue(int)), Qt::DirectConnection );
Never used, but I guess the same should work for invoke:
QMetaObject::invokeMethod(hsv, "updateHsv", Qt::DirectConnection, ...
(the main thread will call changeValue then so the worker thread doesnt need to stop processing to change values => value access should be thread safe!
or you have to process the event queue of that thread:
while(true)
{
[processing]
QApplication::processEvents();
}
I think the simplest solution here may be to take advantage of the fact that Qt Signals/Slots work across threads.
Setup the appropriate slots in the processing thread and then signal them from the GUI thread.
There are all sorts of interesting questions about whether you signal for every user input, or whether you batch up changes for a moment on the GUI side...
There is some ideas for thread sync in the docs: http://doc.qt.io/qt-5/threads-synchronizing.html
Maybe this is stupid question, actually it's appeal, or Qt is just to complicated for me.
Here's the thing:
I'm used to java when writing client-server application, and it's very simple. I would like to do same things in C++ (I'm very familiar with C++ itself), and I choose to learn Qt. I tried to write some applications in qt, but with partial success.
First thing that bothers me is signals and slots. I know how to use them in GUI programming but it confuses me with networking. And there's problem with blocking. When I call BufferedReader's readLine() method in java it blocks until it receives line from socket connection. In Qt I must make sure that there is line available every time, and handle it when there isn't one.
And when I connect QSocket's error signal to some of my custom slots, the signal is emitted when server sends last line and closes the connection, and in client's slot/function that reads I never read that last line. That are some problems I faced so far.
Slots and checking if there is data available makes me confused when I had to implements even the simplest protocols.
Important part:
I tried to find good example on the internet, but problem is that all examples are to complicated an big. Is there anyone how can show me how to write simple client-server application. Server accepts only one client. Client sends textual line containing command. If command is "ADD" or "SUB", server sends "SUP" indicating that command is supported. Otherwise it sends "UNS" and closes the connection. If client receives "SUP" it sends to more lines containing numbers to be subtracted or added. Server responds with result and closes connection.
I know that C++ requires more coding, but in Java this would take only 5 minutes, so it shouldn't take to long to write it in C++ either.
I'm sure this example would be very valuable to anyone who wants to learn networking in Qt.
edit:
This is my try to make the application (described above):
here is the server part:
#ifndef TASK_H
#define TASK_H
#include <QObject>
#include <QTcpServer>
class Task : public QObject
{
Q_OBJECT
public:
Task(QObject *parent = 0) : QObject(parent) {}
public slots:
void run();
void on_newConnection();
void on_error(QAbstractSocket::SocketError);
signals:
void finished();
private:
QTcpServer server;
};
#endif // TASK_H
void Task::run()
{
connect(&server,SIGNAL(newConnection()),this,SLOT(on_newConnection()));
connect(&server,SIGNAL(acceptError(QAbstractSocket::SocketError)),this,SLOT(on_error(QAbstractSocket::SocketError)));
if(server.listen(QHostAddress::LocalHost, 9000)){
qDebug() << "listening";
}else{
qDebug() << "cannot listen";
qDebug() << server.errorString();
}
}
void Task::on_newConnection(){
std::cout << "handeling new connection...\n";
QTcpSocket* socket = server.nextPendingConnection();
QTextStream tstream(socket);
while(!socket->canReadLine()){
socket->waitForReadyRead((-1));
}
QString operation = tstream.readLine();
qDebug() << "dbg:" << operation;
if(operation != "ADD" && operation != "SUB"){
tstream << "UNS\n";
tstream.flush();
socket->disconnect();
return;
}
tstream << "SUP\n";
tstream.flush();
double op1,op2;
while(!socket->canReadLine()){
socket->waitForReadyRead((-1));
}
op1 = socket->readLine().trimmed().toDouble();
qDebug() << "op1:" << op1;
while(!socket->canReadLine()){
socket->waitForReadyRead(-1);
}
op2 = socket->readLine().trimmed().toDouble();
qDebug() << "op2:" << op2;
double r;
if(operation == "ADD"){
r = op1 + op2;
}else{
r = op1 - op2;
}
tstream << r << "\n";
tstream.flush();
qDebug() << "result is: " << r;
socket->disconnect();
}
void Task::on_error(QAbstractSocket::SocketError ){
qDebug() << "server error";
server.close();
}
This is client side (header is similar to server's so I wont post it):
void Task::run()
{
QTcpSocket socket;
std::string temp;
socket.connectToHost(QHostAddress::LocalHost,9000);
if(socket.waitForConnected(-1))
qDebug() << "connected";
else {
qDebug() << "cannot connect";
return;
}
QTextStream tstream(&socket);
QString op;
std::cout << "operation: ";
std::cin >> temp;
op = temp.c_str();
tstream << op << "\n";
tstream.flush();
qDebug() << "dbg:" << op << "\n";
while(!socket.canReadLine()){
socket.waitForReadyRead(-1);
}
QString response = tstream.readLine();
qDebug() << "dbg:" << response;
if(response == "SUP"){
std::cout << "operand 1: ";
std::cin >> temp;
op = temp.c_str();
tstream << op + "\n";
std::cout << "operand 2: ";
std::cin >> temp;
op = temp.c_str();
tstream << op + "\n";
tstream.flush();
while(!socket.canReadLine()){
socket.waitForReadyRead(-1);
}
QString result = tstream.readLine();
std::cout << qPrintable("result is: " + result);
}else if(response == "UNS"){
std::cout << "unsupported operatoion.";
}else{
std::cout << "unknown error.";
}
emit finished();
}
What I could do better?
What are some good practices in similar situations?
When using blocking (not signal/slot mechanism), what is the best way to handle event when other side closes the connection?
Can someone rewrite this to make it look more professional (I just what to see how it supposed to look like, because I think that my solution is far from perfect) ?
Can someone rewrite this using signals and slots?
Thanks you.
Sorry for my English, and probably stupidity :)
Networking with Qt is not that difficult.
Communication between two points is handled by a single class; in the case of TCP/IP, that would be the QTcpSocket class. Both the client and server will communicate with a QTcpSocket object.
The only difference with the server is that you start with a QTcpServer object and call listen() to await a connection...
QTcpServer* m_pTcpServer = new QTcpServer
//create the address that the server will listen on
QHostAddress addr(QHostAddress::LocalHost); // assuming local host (127.0.0.1)
// start listening
bool bListening = m_pServer->listen(addr, _PORT); //_PORT defined as whatever port you want to use
When the server receives a connection from a client QTcpSocket, it will notify you with a newConnection signal, so assuming you've made a connection to a socket in your own class to receive that signal, we can get the server QTcpSocket object to communicate with the client...
QTcpSocket* pServerSocket = m_pServer->nextPendingConnection();
The server will receive a QTcpSocket object for each connection made. The server socket can now be used to send data to a client socket, using the a write method...
pServerSocket->write("Hello!");
When a socket (either client or server) receives data, it emits the readyRead signal. So, assuming you have made a connection to the readyRead signal for the socket, a slot function can retrieve the data...
QString msg = pSocket->readAll();
The other code you'll need is to handle the connect, disconnect and error signals, which you should connect relevant slots for receiving these notifications.
Ensure you only send data when you know the connection has been made. Normally, I would have the server receive a connection and send a 'hello' message back to the client. Once the client receives the message, it knows it can send to the server.
When either side disconnects, the remaining side will receive the disconnect signal and can act appropriately.
As for the client, it will just have one QTcpSocket object and after calling connectToHost, you will either receive a connected signal if the connection was succesfully made, or the error signal.
Finally, you can use QLocalServer and QLocalSocket in the same way, if you're just trying to communicate between processes on the same machine.