Seite 1 von 1

Client Server Kommunikation (beidseitig)

Verfasst: 5. Dezember 2013 00:19
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 ?

Re: Client Server Kommunikation (beidseitig)

Verfasst: 5. Dezember 2013 07:20
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.

Re: Client Server Kommunikation (beidseitig)

Verfasst: 6. Dezember 2013 17:08
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 ?

Re: Client Server Kommunikation (beidseitig)

Verfasst: 6. Dezember 2013 18:25
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?

Re: Client Server Kommunikation (beidseitig)

Verfasst: 7. Dezember 2013 10:21
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 ?

Re: Client Server Kommunikation (beidseitig)

Verfasst: 11. Dezember 2013 20:37
von binio
Kann mir da noch jemand ein Tipp geben ? Wie bekomme ich doch noch den Client vom Server aus angesprochen ?