Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QTcpSocket two way client-server communication

i'm developing an app for Raspberry PI based on socket interface. The main idea is that Raspberry will be connected to a sensor, collect data and send it via WiFi to Android device. From Android I can communicate with sensor sending some commands. I'm a beginner in this kind of development and following some tutorials about QTcpSocket I have created a simple client-server app but it is only in one direction. Server listens for what client is sending. Could you help me to improve it into two way communication? I've read that QTcpSocket doesn't require threading for this kind of problem but I didn't find any solution.

I would appreciate any help!

server.cpp:

#include "server.h"
#include <QTcpServer>
#include <QTcpSocket>
#include <cstdio>
#include <QtDebug>

Server::Server(QObject *parent) :
QObject(parent)
{
    server = new QTcpServer(this);
    connect(server, SIGNAL(newConnection()),
    this, SLOT(on_newConnection()));
}

void Server::listen()
{
    server->listen(QHostAddress::Any, 5100);
}

void Server::on_newConnection()
{
    socket = server->nextPendingConnection();

    if(socket->state() == QTcpSocket::ConnectedState)
    {
        printf("New connection established.\n");
        qDebug()<<socket->peerAddress();
    }
    connect(socket, SIGNAL(disconnected()),
    this, SLOT(on_disconnected()));
    connect(socket, SIGNAL(readyRead()),
    this, SLOT(on_readyRead()));
}

void Server::on_readyRead()
{
    while(socket->canReadLine())
    {
        QByteArray ba = socket->readLine();

        if(strcmp(ba.constData(), "!exit\n") == 0)
        {
            socket->disconnectFromHost();
            break;
        }
        printf(">> %s", ba.constData());
    }
}

void Server::on_disconnected()
{
    printf("Connection disconnected.\n");
    disconnect(socket, SIGNAL(disconnected()));
    disconnect(socket, SIGNAL(readyRead()));
    socket->deleteLater();
}

client.cpp

#include "client.h"
#include <QTcpSocket>
#include <QHostAddress>
#include <cstdio>

Client::Client(QObject *parent) : QObject(parent)
{
    socket = new QTcpSocket(this);
    printf("try to connect.\n");
    connect(socket, SIGNAL(connected()),
    this, SLOT(on_connected()));
}

void Client::on_connected()
{
    printf("Connection established.\n");
    char buffer[1024];
    forever
    {
        while(socket->canReadLine())
        {
            QByteArray ba = socket->readLine();
            printf("from server: %s", ba.constData());
        }
        printf(">> ");
        gets(buffer);
        int len = strlen(buffer);
        buffer[len] = '\n';
        buffer[len+1] = '\0';
        socket->write(buffer);
        socket->flush();
    }

}

void Client::connectToServer()
{
    socket->connectToHost(QHostAddress::LocalHost, 5100);
}
like image 781
Krzysztof Jackowski Avatar asked Mar 24 '23 13:03

Krzysztof Jackowski


1 Answers

From architectural point of view you should define some communication rules (message flow) between your server and client first.

Then just read(write) from(to) instance of QTCPSocket according to defined flow.

You can, for instance, read data on server side, check what you should answer and write response to the same socket from which you have read. For line oriented messages (and only for them) code could look like:

    void Server::on_readyRead()
    {
        // "while" loop would block until at least one whole line arrived
        // I would use "if" instead
        if(socket->canReadLine()) 
        {
            QByteArray ba = socket->readLine();

            QByteArray response;

            // some code which parses arrived message
            // and prepares response

            socket->write(response);
        }
        //else just wait for more data
    }

Personally, I would move parsing and sending responses out from on_readyRead() slot to avoid blocking event loop for too long time, but since you are a beginner in network programming I just wanted to clarify what could be done to implement two way communication.

For more details you can see http://qt-project.org/doc/qt-4.8/qtnetwork.html

Remember about checking if whole message has arrived on both client and server side. If you use your own protocol (not HTTP, FTP nor other standarized) you can add message length on the beginning of message.

like image 199
undercover Avatar answered Apr 02 '23 20:04

undercover