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.
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(); }
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(); }