Client Server Kommunikation (beidseitig)

Alles rund um die Programmierung mit Qt
Antworten
binio
Beiträge: 23
Registriert: 8. März 2010 19:11
Kontaktdaten:

Client Server Kommunikation (beidseitig)

Beitrag von binio »

Ich habe es hinbekommen das der Client sich auf ein Server connected und sogar Daten zum Server schickt. Der Server stellt diese Daten auch erfolgreich dar.
Jetzt möchte ich jedoch auch vom Server zu genau dem Client eine Information (nur Text) schicken.
Also eine Kommunikation in beide Richtung (aber erst nachdem die ersten Infos vom Client zum Server gekommen sind)

Ziel der ganzen Programmierung ist ein Teamviewer fähiges Programm.
Das senden von Daten (Screenshot): Client -> Server habe ich wie oben geschrieben erfolgreich hinbekommen.
Jetzt fehlt nur noch das senden von Daten (Mausposition) zu genau diesen einem verbundenen Client: Server -> Client

Hat jemand für mich ein Tipp oder schon mal von solchen Programmierbeispielen gehört ?
Technik muss dem Menschen dienen, nicht umgekehrt
Flashpixx
Beiträge: 29
Registriert: 10. Juli 2007 12:54
Kontaktdaten:

Re: Client Server Kommunikation (beidseitig)

Beitrag von Flashpixx »

Der Server hat für den Client ein entsprechenden Socket offen, d.h. über den Socket kannst Du vom Server auch Daten zum Client schicken.
binio
Beiträge: 23
Registriert: 8. März 2010 19:11
Kontaktdaten:

Re: Client Server Kommunikation (beidseitig)

Beitrag von binio »

Ok ich habe es versucht und bin gescheitert :(

mysendImage.h

Code: Alles auswählen

#ifndef SENDIMAGE_H
#define SENDIMAGE_H

// QT
#include <QString>
#include <QTcpSocket>
#include <QImage>
#include <QTimer>
#include <QPixmap>
#include <QDesktopWidget>
#include <QApplication>
#include <QtGui/QWidget>
#include <QMainWindow>
#include <QScreen>
#include <QFile>
#include <QDateTime>
#include <QPainter>
#include <QMessageBox>

class SendImage : public QObject{
    Q_OBJECT

public:
    explicit SendImage(QString address, int port);
    void send(QImage image, QString name);
    void SendData(QString data);

private slots:
    void setConnected();
    void sendscreen();
    void akt_status(QAbstractSocket::SocketState);
    void hostFoundComplete();
    void test(QAbstractSocket::SocketError socketError);
    void ReadData();
    void connected();

private:
    void toggleConnection();
    void reallySend(QString name, QImage image);

public:
    QString name;
    QString name_screen;
    QImage image;
    QImage image_screen;
    QString			address;
    int			port;
    QTcpSocket*		socket;
};
#endif // SENDIMAGE_H
mysendImage.cpp

Code: Alles auswählen

#include "mysendimage.h"
#include <QBuffer>

SendImage::SendImage(QString address, int port){
    this->address = address;
    this->port = port;
    socket = new QTcpSocket(this);
    connect(socket, SIGNAL(connected()), SLOT(setConnected()));
    connect(socket, SIGNAL(readyRead()), this, SLOT(ReadData()));

    this->sendscreen();

//SELF
//    QTimer *support_Timer = new QTimer(this);
//    support_Timer->setInterval(1000);
//    support_Timer->start();
//    qDebug()<<"Timer :)";
//    connect(support_Timer, SIGNAL(timeout()), this, SLOT(sendscreen()));
}

void SendImage::setConnected(){
    qDebug()<<"Connected with Server";
    reallySend(this->name, this->image);
}

void SendImage::sendscreen(){
    qDebug()<<"sendscreen";
    QPixmap originalPixmap;
    originalPixmap = QPixmap::grabWindow(QApplication::desktop()->winId());
    QPainter maus(&originalPixmap);
    QPen stift(Qt::black);
    stift.setWidth(10);
    maus.setPen(stift);
    maus.drawEllipse(QCursor::pos().x(),QCursor::pos().y(),20,20);
    image_screen = originalPixmap.toImage().convertToFormat(QImage::Format_MonoLSB,Qt::MonoOnly);
    name_screen = QString("Screen_%1.png").arg(QDateTime::currentDateTime().toString("dd_MM_yyyy-hh_mm_ss"));
    this->send(this->image_screen,this->name_screen);
}

void SendImage::send(QImage image, QString name){
    this->name = name;		// Store the data
    this->image = image;	//
    toggleConnection();		// Start connection
}

void SendImage::reallySend(QString name, QImage image){
    qDebug()<<"Send Image with Name";
    if(socket->state() == QAbstractSocket::ConnectedState){
        qDebug()<<"echtes senden";
        image.setText("name", name);
        QByteArray ba;
        QBuffer buffer(&ba);
        image.save(&buffer, "PNG");
        socket->write(ba);
    }else{
        qDebug("Image has not been send. No connection established!");
    }
    toggleConnection();
}

void SendImage::toggleConnection(){
    if(socket->state() == QAbstractSocket::UnconnectedState){
        socket->connectToHost(this->address, this->port, QIODevice::WriteOnly);
        qDebug()<<"toggleConnection -> : "<<socket->state();
    }else{
        qDebug()<<"toggleConnection disconnectFromHost()";
        socket->disconnectFromHost();
    }
}

void SendImage::ReadData(){
    qDebug()<<"ReadData";
    while(socket->canReadLine()){
        QString line = QString::fromUtf8(socket->readLine()).trimmed();
        qDebug() << line;
    }
}
Serverseitig
libimageserver.h

Code: Alles auswählen

#ifndef IMAGESERVER_H
#define IMAGESERVER_H
#include <QTcpServer>
#include <QList>
#include <QHash>

class QBuffer;
class QTcpSocket;

class ImageServer : public QTcpServer{
    Q_OBJECT

public:
    ImageServer(QObject* parent = 0);
    void setImagePath(QString path);

signals:
    void newImage(QString filename);

private slots:
    void addConnection();
    void removeConnection();
    void receiveImage();

private:
    QString path;
    QList<QTcpSocket*> connections;
    QHash<QTcpSocket*, QBuffer*> buffers;
    QTcpSocket *connection;
};
#endif // IMAGESERVER_H
libimageserver.cpp

Code: Alles auswählen

#include "libimageserver.h"
#include <QBuffer>
#include <QTcpSocket>
#include <QImage>
#include <QDebug>

ImageServer::ImageServer(QObject* parent) : QTcpServer(parent){
    connect(this, SIGNAL(newConnection()), this, SLOT(addConnection()));
    path = "";
}
void ImageServer::setImagePath(QString path){
    this->path = path;
}

void ImageServer::addConnection(){
    qDebug("Adding connection");
    connection = nextPendingConnection();
    connections.append(connection);
    QBuffer* buffer = new QBuffer(this);
    buffer->open(QIODevice::ReadWrite);
    buffers.insert(connection, buffer);
    connect(connection, SIGNAL(disconnected()), SLOT(removeConnection()));
}

void ImageServer::removeConnection(){
    qDebug("Remove connection");
    receiveImage();
    connection->write(QString("test vom Server\n").toUtf8());
    QTcpSocket* socket = static_cast<QTcpSocket*>(sender());
    QBuffer* buffer = buffers.take(socket);
    buffer->close();
    buffer->deleteLater();
    connections.removeAll(socket);
    socket->deleteLater();
}

void ImageServer::receiveImage(){
    QTcpSocket* socket = static_cast<QTcpSocket*>(sender());
    QBuffer* buffer = buffers.value(socket);
    // missing some checks for returns values for the sake of simplicity
    qint64 bytes = buffer->write(socket->readAll());
    // go back as many bytes as we just wrote so that it can be read
    buffer->seek(buffer->pos() - bytes);

    QImage image;
    image.loadFromData(buffer->buffer());
    if(image.isNull())
        qDebug("The image is null. Something failed.");
    QString filename = path + "\\" + image.text("name");
    image.save(filename);

    qDebug("image received");
    emit newImage(filename);
}
Also so bekomme ich wunderbar das Bild(Serverseitig) und kann es in meiner aufrufenden Anwendung anzeigen.
Auf dem Server aber schreibe ich:

Code: Alles auswählen

...
connection->write(QString("test vom Server\n").toUtf8());
...
in der Methode: "void ImageServer::removeConnection(){"
Mit diesem Aufruf habe ich jetzt erwartet das Clientseitig "void SendImage::ReadData(){" aufgerufen wird und mit:

Code: Alles auswählen

    qDebug()<<"ReadData";
    while(socket->canReadLine()){
        QString line = QString::fromUtf8(socket->readLine()).trimmed();
        qDebug() << line;
    }
mein Text vom Server ausgegeben wird. Dies passiert jedoch nicht nicht einmal die qDebug<<"ReadData"; wird ausgegeben, als ob er nicht einmal den Slot "ReadData()" ausrufen würde.
Oder habe ich prinz. ein Denkfehler ?
Technik muss dem Menschen dienen, nicht umgekehrt
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Client Server Kommunikation (beidseitig)

Beitrag von Christian81 »

Du versuchst Daten zu schicken in dem Slot in dem Du auf das disconnected() - Signal reagierst? Wie sollte man noch was schicken können wenn der Socket disconnected ist?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
binio
Beiträge: 23
Registriert: 8. März 2010 19:11
Kontaktdaten:

Re: Client Server Kommunikation (beidseitig)

Beitrag von binio »

Habe gedacht es ist wie der Destruktor zu verstehen.
Wollte darin den Verbindungsabbau steuern :) bzw. meine Nachricht noch abschicken :)

Habe nun:

Code: Alles auswählen

void ImageServer::addConnection(){
    qDebug("Adding connection");
    connection = nextPendingConnection();
    connections.append(connection);
    QBuffer* buffer = new QBuffer(this);
    buffer->open(QIODevice::ReadWrite);
    buffers.insert(connection, buffer);
    connection->write(QString("test vom Server\n").toUtf8());
    connect(connection, SIGNAL(disconnected()), SLOT(removeConnection()));
}
H.d. das "zurückschreiben" an den Client in newConnection drin. Jedoch zerstöre ich mir damit jetzt das Bild.
Gibt es evtl. die Möglichkeit Clientseitig auf eine Methode vom Server zuzugreifen. Wie ein Funktionsaufruf(Methodenaufruf) in einem Objekt ?
Technik muss dem Menschen dienen, nicht umgekehrt
binio
Beiträge: 23
Registriert: 8. März 2010 19:11
Kontaktdaten:

Re: Client Server Kommunikation (beidseitig)

Beitrag von binio »

Kann mir da noch jemand ein Tipp geben ? Wie bekomme ich doch noch den Client vom Server aus angesprochen ?
Technik muss dem Menschen dienen, nicht umgekehrt
Antworten