String TCP Übertragung

Alles rund um die Programmierung mit Qt
Antworten
Tiim
Beiträge: 11
Registriert: 20. August 2011 16:54

String TCP Übertragung

Beitrag von Tiim »

Guten Tag liebe Qt Community

Ich bin ein ziemlicher Neuling in Qt, wollte aber trotzdem mal versuchen, einen TCP Chat zu schreiben, ohne die Beispiele zu Copy-Pasten.
Ich hab es schon soweit, dass sich der Client mit dem Server verbindet, und dieser den Socket in einen QVector schreibt.
Wenn ich jetzt aber den Client einen String zum Server (oder umgekehrt) senden lasse, kommt (augenscheinlich) nichts an.

Hier mal meine Sources:

client main:

Code: Alles auswählen

#include <QtGui/QApplication>
#include "client.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Client w;
    w.show();

    return a.exec();
}
client.h:

Code: Alles auswählen

#ifndef CLIENT_H
#define CLIENT_H

#include <QtGui>
#include <QTcpSocket>

namespace Ui {
    class Client;
}

class Client : public QMainWindow
{
    Q_OBJECT

public:
    explicit Client(QWidget *parent = 0);
    ~Client();

private:
    Ui::Client *ui;
    QTcpSocket *sock;

    void send(QString str);
    void print(QString str);

private slots:
    void OnButtonConnect();
    void OnButtonSend();
    void OnSockConnected();
    void OnSockError(QAbstractSocket::SocketError);
    void OnSockDisconnected();
    void OnReadyRead();

};

#endif // CLIENT_H
client.cpp:

Code: Alles auswählen

#include "client.h"
#include "ui_client.h"

Client::Client(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Client)
{
    ui->setupUi(this);
    ui->_inpEdit->setEnabled(false);
    ui->_sendButton->setEnabled(false);

    ui->_listView->setReadOnly(true);
    connect(ui->_connectButton,SIGNAL(clicked()),this,SLOT(OnButtonConnect()));
    connect(ui->_sendButton,SIGNAL(clicked()),this,SLOT(OnButtonSend()));

}

Client::~Client()
{
    delete ui;
}

void Client::OnButtonConnect()
{
    sock = new QTcpSocket(this);
    connect(sock,SIGNAL(connected()),this,SLOT(OnSockConnected()));
    connect(sock,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(OnSockError(QAbstractSocket::SocketError)));
    connect(sock,SIGNAL(readyRead()),this,SLOT(OnReadyRead()));
    connect(sock,SIGNAL(disconnected()),this,SLOT(OnSockDisconnected()));
    sock->connectToHost(ui->_ipEdit->text(),ui->_portEdit->value());
}
void Client::OnSockConnected()
{
    ui->_sendButton->setEnabled(true);
    ui->_inpEdit->setEnabled(true);
    ui->_connectButton->setEnabled(false);
    send("New Client Connected!");
}

void Client::OnSockError(QAbstractSocket::SocketError)
{
    print(tr("Socket Error: %1").arg(sock->errorString()));
}
void Client::OnSockDisconnected()
{
    print("Disconnect!");
    sock->disconnect();
    sock->deleteLater();
    ui->_connectButton->setEnabled(true);
    ui->_inpEdit->setEnabled(false);
    ui->_sendButton->setEnabled(false);
}
void Client::OnButtonSend()
{
    send(ui->_inpEdit->text());
    ui->_inpEdit->clear();
}
void Client::OnReadyRead()
{
    while(sock->canReadLine())
        print(sock->readLine());
}

void Client::send(QString str)
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out << str <<endl;
    sock->write(block);

}
void Client::print(QString str)
{
    ui->_listView->appendPlainText(str);
}
server main:

Code: Alles auswählen

#include <QtGui/QApplication>
#include "server.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Server w;
    w.show();

    return a.exec();
}
server.h

Code: Alles auswählen

#ifndef SERVER_H
#define SERVER_H

//#include <QByteArray>
#include <QMessageBox>
#include <QtGui>
#include <QTcpServer>
#include <QTcpSocket>
#include <QVector>

namespace Ui {
    class Server;
}

class Server : public QMainWindow
{
    Q_OBJECT

public:
    explicit Server(QWidget *parent = 0);
    ~Server();


private:
    Ui::Server *ui;
    //Server
    QTcpServer* serv;
    QVector<QTcpSocket*> socks;
    //Funcs
    void print(QString str);
    void send(QString str);

private slots:
    void OnNewConnection();
    void OnReadyRead();
    void OnDisconnect();
    void OnButtonSend();
    void OnButtonDisconnect();
};

#endif // SERVER_H
server.cpp

Code: Alles auswählen

#include "server.h"
#include "ui_server.h"

Server::Server(QWidget *parent) :QMainWindow(parent),ui(new Ui::Server)
{
    ui->setupUi(this);
    ui->_disconnectButton->setEnabled(false);
    ui->_listView->setReadOnly(true);
    ui->_sendButton->setEnabled(false);
    ui->_sendEdit->setEnabled(false);

    serv = new QTcpServer(this);
    connect(serv,SIGNAL(newConnection()),this,SLOT(OnNewConnection()));
    if (!serv->listen())
    {
        QMessageBox::critical(this,tr("Error"),tr("Server can't start: %1").arg(serv->errorString()));
        close();
        return;
    }
    print(tr("Port: %1").arg(serv->serverPort()));
    connect(ui->_sendButton,SIGNAL(clicked()),this,SLOT(OnButtonSend()));
    connect(ui->_clearButton,SIGNAL(clicked()),ui->_listView,SLOT(clear()));
    connect(ui->_disconnectButton,SIGNAL(clicked()),this,SLOT(OnButtonDisconnect()));

}

Server::~Server()
{
    delete ui;
}

void Server::print(QString str)
{
    ui->_listView->appendPlainText(tr("%1 %2").arg(str).arg("\n"));
}

void Server::OnNewConnection()
{
    if (socks.count() < 1)
    {
        ui->_disconnectButton->setEnabled(true);
        ui->_sendButton->setEnabled(true);
        ui->_sendEdit->setEnabled(true);
    }
    socks.append(serv->nextPendingConnection());
    connect(socks.at(socks.count()-1),SIGNAL(readyRead()),this,SLOT(OnReadyRead()));
    connect(socks.at(socks.count()-1),SIGNAL(disconnected()),this,SLOT(OnDisconnect()));
}
void Server::OnReadyRead()
{
    for(int i=0;i<socks.count();i++)
    {
        while(socks.at(i)->canReadLine())
            print(socks.at(i)->readLine());
    }
}
void Server::OnDisconnect()
{
    for(int i=0;i<socks.count();i++)
    {
        if (socks.at(i)->state() != QAbstractSocket::ConnectingState &&
            socks.at(i)->state() != QAbstractSocket::ConnectedState  &&
            socks.at(i)->state() != QAbstractSocket::ListeningState)
        {
            socks.at(i)->disconnect();
            socks.at(i)->close();
            socks.at(i)->deleteLater();
            print(tr("Client Nr %1 Disconected").arg(i));
            socks.remove(i);
        }
    }
}
void Server::send(QString str)
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out << str <<endl;
    for(int i=0;i<socks.count();i++)
    {
        socks.at(i)->write(block);
    }
}
void Server::OnButtonSend()
{
    QString str = ui->_sendEdit->text();
    if (!str.isEmpty())
    send(str);
    ui->_sendEdit->clear();
}

void Server::OnButtonDisconnect()
{
    for(int i=0;i<socks.count();i++)
    {
        socks.at(i)->disconnect();
        socks.at(i)->close();
        socks.at(i)->deleteLater();
        print(tr("Client Nr %1 Disconected").arg(i));
        socks.remove(i);
    }
}
Die Dateien Server.cpp und Client.cpp sind leider etwas unaufgeräumt, da ich neuere Implementationen einfach an den Schluss geschrieben habe.
Vielen Dank, falls sich das jemand anschauen würde.

/Edit: Ich glaube ich habe ins falsche Forum gepostet, könnte man das ggf. verschieben?
Zuletzt geändert von Tiim am 20. August 2011 20:57, insgesamt 1-mal geändert.
Seit August 2011 Qt Anfänger
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: String TCP Übertragung

Beitrag von Christian81 »

Wenn man mit einem QDataStream reinschreibt sollte man auch mit QDataStream lesen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Tiim
Beiträge: 11
Registriert: 20. August 2011 16:54

Re: String TCP Übertragung

Beitrag von Tiim »

Hmm..

Ich hab es jetzt mal so probiert:

Funktion OnReadyRead() client.cpp

Code: Alles auswählen

        QString str;
        QDataStream stream(socks.at(i));
        stream >> str;
        if (str.contains('\n'))
            print(str);
Funktion OnReadyRead() server.cpp

Code: Alles auswählen

        QString str;
        QDataStream stream(sock);
        stream >> str;
        if (str.contains('\n'))
            print(str);
Was jedoch nichts bringt, wie kann ich denn mit einem Stream vom Socket lesen?
Ich hab jetzt noch eine Kompilerwarnung gesehen, die ich vorhin übersehen habe, deren Sinn sich mir jedoch nicht erschliesst:

Code: Alles auswählen

/home/tiim/Arbeitsfläche/Programmieren/C++/QT/Chat/Server/Chat-build-desktop/../Chat/server.cpp:77: Warnung:the address of ‘QTextStream& endl(QTextStream&)’ will always evaluate as ‘true’
Seit August 2011 Qt Anfänger
Spinoza
Beiträge: 23
Registriert: 4. März 2011 01:07

Re: String TCP Übertragung

Beitrag von Spinoza »

Zwei Möglichkeiten:

Code: Alles auswählen

QByteArray blubb = tcpSocket.readAll();
QDataStream stream(&blubb);
QString string;
stream >> string;
oder mittels bytesAvailable() gucken wieviel bytes gelesen werden können, einen Puffer mit entsprechen der Größe anlegen (char-array) und mit read() einlesen.

Beides natürlich im readyRead slot.
Tiim
Beiträge: 11
Registriert: 20. August 2011 16:54

Re: String TCP Übertragung

Beitrag von Tiim »

Vielen Dank, so funktioniert es, es muss nur das "&" vor dem "blubb" weg, da es als Referenz übergeben wird
Seit August 2011 Qt Anfänger
Spinoza
Beiträge: 23
Registriert: 4. März 2011 01:07

Re: String TCP Übertragung

Beitrag von Spinoza »

Tiim hat geschrieben:Vielen Dank, so funktioniert es, es muss nur das "&" vor dem "blubb" weg, da es als Referenz übergeben wird
Vorsicht, der Konstruktor der die Referenz nimmt, ist read only. Wenn du in das bytearray schreiben willst, solltest du den Konstruktor mit Zeiger und entsprechendem OpenMode nehmen.
Antworten