QTcpSocket les deux sens de communication client-serveur
je suis le développement d'une application pour la Raspberry PI basé sur socket interface. L'idée principale est que la Framboise sera connecté à un capteur, recueillir les données et de les envoyer via le wi-fi pour appareil Android. À partir d'Android je peux communiquer avec capteur d'envoyer certaines commandes. Je suis un débutant dans ce genre de développement, et à la suite de certains des tutoriels à propos de QTcpSocket j'ai créé un simple client-serveur de l'app, mais c'est seulement dans une direction. Le serveur est à l'écoute de ce que le client envoie. Pourriez-vous m'aider à l'améliorer en communication dans les deux sens? J'ai lu que QTcpSocket ne nécessite pas de filetage pour ce genre de problème mais je ne trouve pas de solution.
J'apprécierais toute aide!
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] = '#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);
}
';
socket->write(buffer);
socket->flush();
}
}
void Client::connectToServer()
{
socket->connectToHost(QHostAddress::LocalHost, 5100);
}
OriginalL'auteur Krzysztof Jackowski | 2013-06-17
Vous devez vous connecter pour publier un commentaire.
Du point de vue architectural, vous devez définir certaines règles de communication (flux de messages) entre votre serveur et le client d'abord.
Puis il suffit de lire(et écrire) à partir de(pour) l'instance de QTCPSocket en fonction de l'écoulement.
Vous pouvez, par exemple, de lire les données sur le côté serveur, vérifiez que vous devez répondre et écrire la réponse à la même prise à partir de laquelle vous avez lu. Pour la ligne orientés messages (et seulement pour eux) code pourrait ressembler à:
Personnellement, je voudrais déplacer l'analyse et l'envoi des réponses de on_readyRead() fente pour éviter de bloquer la boucle d'événement trop longtemps, mais puisque vous êtes un débutant dans la programmation de réseau je voulais juste préciser ce qui pourrait être fait pour mettre en œuvre une communication bidirectionnelle.
Pour plus de détails, vous pouvez voir http://qt-project.org/doc/qt-4.8/qtnetwork.html
Rappelez-vous il s'agit de vérifier si le message est arrivé sur à la fois côté client et serveur. Si vous utilisez votre propre protocole (HTTP, FTP, ni d'autres standarized) vous pouvez ajouter de la longueur du message sur le début du message.
Votre application ne s'arrêtera pas en attendant readyRead() du signal. Quand il y a le prêt-à-lire les données dans le support, il envoie le signal, votre on_readyRead() slot est appelé. Permet de lire des données, envoyer la réponse (ou pas, si il n'est pas nécessaire) et de contrôle remonte à l'événement principal de la boucle, où votre application peut traiter d'autres événements. Dans QT on appelle ça un "non bloquant" comportement.
ok, je comprends. Le truc c'est que j'ai besoin de serveur pour envoyer des données tout le temps et le client doit envoyer de temps en temps seulement. Donc je ne peux pas écrire sur côté serveur dans on_readyRead() la méthode parce qu'elle ne s'exécute que lorsque le client va envoyer quelque chose. La question est de savoir où dois-je écrire des données sur le côté serveur? Est-il un slot que je peux utiliser pour ce problème?
Il n'y a pas de disons "générique" de la solution. Tout d'abord cela dépend de ce que va être votre fournisseur de données. Dans le cas simple de votre serveur pourrait être un fournisseur de données elle-même. Ensuite, vous avez à stocker socket reçu dans on_newConnection() logement c'est à dire en tant que membre de serveur, de mettre en œuvre la collecte de données, la fonctionnalité et d'écrire des données collectées, stockées socket. Une meilleure solution serait de séparer fournisseur de données héritées de QObject. Vous pourriez mettre en œuvre la communication entre eux à l'aide du signal-slot du modèle.
Merci pour votre temps et votre aide! Je suppose que le signal-slot modèle fera le travail pour moi.
OriginalL'auteur undercover
Tout ce que vous devez faire est d'écrire/lire à partir de la socket du client ou du serveur. Une connexion TCP est déjà connexion bidirectionnelle.
Vous pouvez peut-être avoir quelques problèmes avec votre
forever
boucle dansClient
. Vous devriez vraiment utiliser lesreadyRead
signal sur la prise, de la même manière que vous le faites pour le serveur et déposer leforever
boucle.Poignée de saisie au clavier dans un non-bloquant manière plutôt que d'utiliser
gets()
.gets()
va bloquer le thread principal et l'empêcher de couler la boucle d'événements. Ce n'est pas la meilleure façon de traiter les choses dans votre cas, puisque vous voulez être capable de gérer des données à partir du serveur et de l'utilisateur en même temps.Peut-être jeter un oeil à ce qui concerne la gestion clavier à partir d'une application console:
aide-qtextstream de lecture de l'entrée standard stdin-dans-un-non-blocage de la mode
Sinon faire un GUI application et de l'utilisation d'un
QPlainTextEdit
.OriginalL'auteur Pete