Barra laterale

programmazione:qt:semplice_echo_server_client_tcp

Semplice echo server con client tcp

Autore: Fabio Di Matteo
Ultima revisione: 14/03/2014

Lo scopo di questo articolo è quello di realizzare un (molto) semplice echo server con client entrambi di tipo tcp. L'esempio che segue è stato compilato senza problemi sia con le qt 5.x che le qt 4.8 .
Innanzi tutto cominciamo con il dire che i socket in qt vengono correttamente usati tramite alcuni segnali (SIGNAL) che notificano un particolare evento. Come per esempio l'avvenuta connessione di un client su un server, oppure la disconnessione o ancora la ricezione di dati da parte di un client etc… Nel nostro esempio useremo soltanto un paio di segnali giusto per far funzionare lo scambio dei dati.

Output della nostra applicazione:

Client

Client partito...
Connesso al server...
<SERVER>"Ciao Client inserisci una stringa:"
->ciao
<SERVER>ciao

Server

Server partito. 
<CLIENT>ciao

Di seguito il codice del client e del server abbondantemente commentato.

Server

Il server che andremo a scrivere è un server bloccante, ovvero capace di accettare una sola connessione per volta. Per compilare i progetti diamo i soliti qmake e make nel terminale dalla cartella del progetto server o quella del client.

Server.pro

QT       += core

QT       -= gui
QT       += network

TARGET = Server
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app


SOURCES += main.cpp \
    myserver.cpp

HEADERS += \
    myserver.h

myserver.h

#ifndef MYSERVER_H
#define MYSERVER_H
 
#include <QObject>
#include <QDebug>
#include <QTcpServer>
#include <QTcpSocket>
 
 
class MyServer : public QObject
{
    Q_OBJECT
public:
    explicit MyServer(QObject *parent = 0);
 
signals:
 
 
public slots:
    void newConnection();
 
 
private:
    QTcpServer *server;
 
};
 
#endif // MYSERVER_H

myserver.cpp

#include "myserver.h"
#include <QByteArray> //only for QByteArray object
#include <QTime>
#include <QCoreApplication>
 
MyServer::MyServer(QObject *parent) :
    QObject(parent)
{
    server = new QTcpServer(this);
    connect(server, SIGNAL(newConnection()),this, SLOT(newConnection()) ); //non appena arrivano nuove connessioni esegue newConnection()
 
 
    if (!server->listen(QHostAddress::Any, 1234)) //mette in ascolto il server sulla porta 1234 se possibile
    {
        qDebug()<< "Il Server non puo' partire.";
 
    }else{
        qDebug()<< "Server partito.";
    }
}
 
 
 
 
 
void MyServer::newConnection()
{
    QTcpSocket *socket= server->nextPendingConnection(); // "Aggancio" il socket al server (bind)
    socket->write("Ciao client! Inserisci una stringa:")  ; //mando un messaggio di benvenuto al client
    socket->flush();
 
    QByteArray mykeypass; //Array di byte utilizzato per scambiare dati con il client
    bool quit=false;      //una varibile booleana per uscire dal while
    while(quit==false)
    {
 
        if (socket->waitForReadyRead(3000)) //aspetto che venga emesso nel client il segnale readyRead()
        {
            //Leggo e mostro cosa ha scritto il client
            mykeypass=  socket->readLine();
            qDebug()<<"<CLIENT>"<< mykeypass;
            socket->flush();
 
            //Invio al client l'eco di quello che ha scritto
            socket->write(mykeypass);
            socket->flush();
        }
        if (strcmp(mykeypass.data(),"quit")==0) //Mi serve solo per uscire dal programma
        {
            quit=true; qDebug()<<"Esco...";
            socket->close();
            qApp->exit();
        }
 
    }
 
 
 
}

main.cpp

#include <QCoreApplication>
#include "myserver.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
 
    MyServer Server;
 
    return a.exec();
}

Client

Un semplice client che legge il messaggio di benvenuto del server, poi chiede all'utente di scrivere qaulcosa, lo invia al server e ne attende la risposta. Dopodicche richiede di nuovo l'input dell'utente, lo invia al server e così via …
Per compilare i progetti diamo i soliti qmake e make nel terminale dalla cartella del progetto server o quella del client.

Client.pro

QT       += core
QT       += network

QT       -= gui

TARGET = Client
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app


SOURCES += main.cpp \
    myclient.cpp

HEADERS += \
    myclient.h

myclient.h

#ifndef MYCLIENT_H
#define MYCLIENT_H
 
#include <QObject>
#include <QDebug>
#include <QTcpSocket>
 
class myClient : public QObject
{
    Q_OBJECT
public:
    explicit myClient(QObject *parent = 0);
 
 
signals:
 
public slots:
    void myread();      //segnali spiegati in myclient.cpp
    void onConnected();
 
private:
    QTcpSocket *socket; //socket utilizzato per la connessione
    QByteArray data; //array per scambiare messaggi con il server
 
};
 
#endif // MYCLIENT_H

myclient.cpp

#include "myclient.h"
#include <iostream>
 
myClient::myClient(QObject *parent) :
    QObject(parent)
{
    socket= new  QTcpSocket(this);
    socket->connectToHost("192.168.1.2", 1234); //mi connetto al server(ip e porta)
 
   connect(socket, SIGNAL(connected()),this,SLOT(onConnected())); //quando si connette esegue onConnect()
   connect(socket, SIGNAL(readyRead()),this,SLOT(myread()));      //quando la connessione è pronta esegue myread()
 
    qDebug()<<"Client partito...";
 
 
}
 
void myClient::onConnected()
{
    qDebug()<<"Connesso al server...";
 
 
}
 
 
 
void myClient::myread()
{
 
    data=socket->readLine(); //Catturo il msg di benvenuto del server
    socket->flush();        // e lo mostro.
    qDebug()<<data;
 
 
    while (1)
    {
 
        std::cout << "\n->";        //Catturo l'input da tastiera
        std::cin >> data.data();
        socket->write(data); //Mando al server quello che ho scritto
        socket->waitForBytesWritten();  //aspettando che arrivi correttamente.
        socket->flush();
 
 
 
        socket->waitForReadyRead(); //Aspetto che la risposta del server
        data=socket->readLine();    //sia disponibile e la leggo
        socket->flush();
        qDebug()<<"<SERVER>"<<data;
    }
}

main.cpp

#include <QCoreApplication>
#include "myclient.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    myClient mClient;
 
    return a.exec();
}

programmazione/qt/semplice_echo_server_client_tcp.txt · Ultima modifica: 18/04/2018 - 15:48 (modifica esterna)