QtNetwork modulin laajennos.
QxtRPCPeer-luokka
QxtRPCPeer-luokka tarjoaa mahdollisuuden signaalien lähettämiseen verkkoyhteyden välityksellä.
Seuraavana esimerkki, jossa esitellään käyttäjän (Client) ja serverin (Server) toiminta, sekä pieni pääohjelma jossa käyttäjä yhdistetään serveriin. Ideana on, että serveriin (joka esimerkiksi ylläpitää jonkin laitteen toimintaa) voidaan ottaa yhteys verkosta.
tcp_client.h
#ifndef TCP_CLIENT_H #define TCP_CLIENT_H #include <QxtNetwork/qxtrpcpeer.h> class TCPClient : public QObject { Q_OBJECT public: TCPClient(); ~TCPClient(); private: /// QxtRPCPeer-olio joka huolehtii fyysisesti serverille yhdistämisestä /// ja signaalin lähettämisestä/vastaanottamisesta QxtRPCPeer *client; /// Serverin IP QString hostIp; /// Serverin portti int hostPort; /// Ollaanko yhteydessä vai ei bool connected; signals: /// Signaalin (viestin) lähettäminen serverille void sendSignal(QVector<QString>); /// Signaali, kun serveriin yhdistäminen onnistuu void connectedToServer(); /// Signaali, kun serveriin yhdistäminen epäonnistuu void serverError(); private slots: /// Slotti, joka yhdistää käyttäjän serveriin void connectToServer(); /// Slotti, joka yhdistää käyttäjän serveriin (annettuun ip-osoitteeseen (QString) /// ja annettuun porttiin (int)) void connectToServer(QString, int); /// Yhteyden katkaiseminen serveriin void disconnectFromServer(); /// Viestin lähetys, aktivoi sendSignal()-signaalin void sendData(QVector<QString>); /// Viestin vastaanotto serveriltä (esim. käyttöliittymän päivittäminen uusilla tiedoilla) void receiveData(QVector<QString>); /// Ilmoitus mikäli yhteyden luominen onnistui (ei pakollinen) void connectionEstablished(); /// Ilmoitus mikäli yhteyden muodostamisessa ilmenee ongelmia (ei pakollinen) void connectionError(); }; #endif // TCP_CLIENT_H
tcp_client.cpp
#include "tcp_client.h" TCPClient::TCPClient() { /// Olion luominen client = new QxtRPCPeer(); /// Oletus IP, johon yhdistetään mikäli käyttäjä ei syötä IP:tä hostIp = "127.0.0.1"; /// Oletusportti johon yhdistetään hostPort = 45123; /// Ollaanko yhteydessä? Oletuksena false connected = false; /// Jotta signaaleihin voidaan yhdistää QVector-tyyppisiä parametreja, on ne määrittettävä seuraavasti qRegisterMetaTypeStreamOperators< QVector<QString> >("QVector<QString>"); /// Liitetään signaalit slotteihin connect(this->client, SIGNAL(connectedToServer()), this, SLOT(connectionEstablished())); connect(this->client, SIGNAL(serverError(QAbstractSocket::SocketError)), this, SLOT(connectionError())); /// attachSignal-funktio kapseloi signaalin muotoon, jossa se voidaan lähettää verkkoyhteyden yli /// Funktion QString-parametri on tunniste, jolla signaali tunnistetaan serverin puolella ja /// pystytään yhdistämään tiettyyn slottiin. client->attachSignal(this, SIGNAL(sendSignal(QVector<QString>)), QString("signalToServer")); /// attachSlot-funktio vastaanottaa serveriltä tullevan kapseloidun signaalin, /// joka välitetään receiveData-slotille client->attachSlot(QString("signalFromServer"), this, SLOT(receiveData(QVector<QString>))); } TCPClient::~TCPClient() { /// Poistetaan muodostettu olio muistin säästämiseksi delete client; } /// Yhdistetään serveriin oletusarvoilla tai käyttäjän antamilla arvoilla void TCPClient::connectToServer() { /// Connect metodi muodostaa connectedToServer- tai serverError-signaalin client->connect(this->hostIp, this->hostPort); } void TCPClient::connectToServer(QString ip, int port) { client->connect(ip, port); } void TCPClient::disconnectFromServer() { client->disconnectServer(); connected = false; } void TCPClient::sendData(QVector<QString> data) { emit sendSignal(data); } void TCPClient::receiveData(QVector<QString>) { qDebug() << "message from server"; } void TCPClient::connectionEstablished() { connected = true; qDebug() << "connected"; } void TCPClient::connectionError() { qDebug() << "connection error"; }
tcp_server.h
#ifndef TCP_SERVER_H #define TCP_SERVER_H #include <QxtNetwork/qxtrpcpeer.h> class TCPServer : public QObject { Q_OBJECT public: TCPServer(); ~TCPServer(); /// Serverin käynnistäminen oletusarvoilla void startServer(); /// Serverin käynnistäminen käyttäjän antamilla parametreilla void startServer(QHostAddress, int); /// Serverin pysäyttäminen void stopServer(); private: /// QxtRPCPeer-olio joka huolehtii fyysisesti serverin toiminnasta (uusien yhteyksien /// kuuntelusta, signaalien vastaanottamisesta/lähettämisestä jne.) QxtRPCPeer *server; /// Serverin ip-osoite QHostAddress serverIp; /// Serverin käyttämä portti int serverPort; /// Lista pitämään kirjaa aktiivisista yhteyksistä (käyttäjistä/clienteista) QList<quint64> clients; signals: /// Signaali, joka muodostetaan käyttäjän yhdistyessä serverille void clientConnected(quint64); /// Signaali käyttäjän katkaistaessa yhteyden void clientDisconnected(quint64); /// Signaali, joka lähetetään takaisin käyttäjälle (esim. käyttöliittymän päivittäminen) void sendSignal(QVector<QString>); private slots: /// Slotti jossa lisätään käyttäjä yhteyslistaan (clients) jne. void newClient(quint64); /// Slotti, jossa poistetaan käyttäjä yhteyslistasta tämän katkaistaessa yhteyden void deleteClient(quint64); /// Slotti joka huolehtii käyttäjältä tulevan signaalin käsittelystä void receiveSignal(quint64, QVector<QString>); }; #endif // TCP_SERVER_H
tcp_server.cpp
#include "tcp_server.h" TCPServer::TCPServer() { server = new QxtRPCPeer(); serverIp = QHostAddress::Any; serverPort = 45123; /// Signaalien ja slottien yhdistäminen Client-puolen tapaan qRegisterMetaTypeStreamOperators< QVector<QString> >("QVector<QString>"); /// Käyttäjältä tulevassa signaalissa on lisänä quint64-tyyppinen muuttuja, joka on yhteyden ID server->attachSlot(QString("signalToServer"), this, SLOT(receiveSignal(quint64, QVector<QString>))); server->attachSignal(this, SIGNAL(sendSignal(QVector<QString>)), QString("signalFromServer")); connect(this->server, SIGNAL(clientConnected(quint64)), this, SLOT(newClient(quint64))); connect(this->server, SIGNAL(clientDisconnected(quint64)), this, SLOT(deleteClient(quint64))); } TCPServer::~TCPServer() { delete server; } void TCPServer::startServer() { /// Käynnistetään serveri listen-funktiolla, jolloin se kuuntelee jatkuvasti uusia yhteyksiä /// Huom. Client-puolella ei käytetä listen-funktiota, vaan pelkästään connect-funktiota server->listen(this->serverIp, this->serverPort); qDebug() << "server up"; } void TCPServer::startServer(QHostAddress address, int port) { server->listen(address, port); qDebug() << "server up"; } void TCPServer::stopServer() { server->stopListening(); clients.empty(); qDebug() << "server down"; } void TCPServer::newClient(quint64 clientId) { clients.append(clientId); qDebug() << clientId << " connected"; } void TCPServer::deleteClient(quint64 clientId) { int delClient = clients.indexOf(clientId); clients.removeAt(delClient); qDebug() << clientId << " disconnected"; } void TCPServer::receiveSignal(quint64 connectionId, QVector<QString> data) { // Tee jotain data:lle // Lähetetään tietoa serverin tilasta takaisin käyttäjälle // emit sendSignal(vector); }
main.cpp
///Pääohjelma