[gelöst] QTcpServer und setMaxPendingConnections

Alles rund um die Programmierung mit Qt
Antworten
ms47
Beiträge: 35
Registriert: 22. Januar 2009 10:02

[gelöst] QTcpServer und setMaxPendingConnections

Beitrag von ms47 »

Hallo,

ich möchte einen Tcp-Server schreiben, wo nur eine Verbindung erlaubt sein soll. Alle anstehenden Verbindungen sollen dann nacheinander abgearbeitet werden.
Nun habe ich in den Dokus zu Qt geschaut und es so verstanden, dass dafür "setMaxPendingConnections" http://doc.trolltech.com/4.6/qtcpserver ... onnections sein soll. Der Server akzeptiert dann keine neuen Verbindungen, aber diese werden vom Betriebssystem in einer Queue gespeichert.
Leider funktioniert das nicht. Starte ich gleichzeitig zwei Clients, werden beide Requests auch direkt zugelassen. Bei kleinen Übertragungen, die in ein Netzwerk-Paket hineinpassen ist das kein Problem, aber wenn die Datei ein paar MB beträgt, dann gibts Chaos.
Habe ich da was mit dem setMaxPendingConnections falsch verstanden? Bin für jeden Tipp dankbar.

Server-Code:

Code: Alles auswählen

#include "server.h"

Server::Server()
{
    startServer();
}

Server::~Server()
{

}

void Server::startServer()
{
    server = new QTcpServer();
    server->setMaxPendingConnections(1);
    connect(server, SIGNAL(newConnection()), this, SLOT(getNewConnection()));
    if(!server->listen(QHostAddress("192.168.0.151"), 6789))
    {
        qDebug() << __LINE__ << server->errorString();
        return;
    }
}

//wird mit jeder neuen Verbindung eines Clienten aufgerufen
void Server::getNewConnection()
{
    qDebug() << "Neue Verbindung eingegangen";
    socket = server->nextPendingConnection();
    connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
    connect(socket, SIGNAL(disconnected()), this, SLOT(readFinished()));
    connect(socket, SIGNAL(readyRead()) , this, SLOT(readRequest()));
}

//wird mit jedem Paket-Empfang aufgerufen
void Server::readRequest()
{
    QByteArray data = socket->readAll();
    qDebug() << "\tEmpfangene Bytes: " << data.size();
}

//wird aufgerufen wenn der Client disconnected
void Server::readFinished()
{
    qDebug() << "read finished";
}
Client-Code:

Code: Alles auswählen

#include "client.h"

Client::Client(QString id)
{
    this->id = id;
    socket = new QTcpSocket();
    connect(socket, SIGNAL(connected()), this, SLOT(connectionToServerIsDone()));

    connectionTimer = new QTimer();
    connect(connectionTimer, SIGNAL(timeout()), this, SLOT(connectToServer()));
}

void Client::startConnection()
{
    connectionTimer->start(5000);
}

void Client::connectToServer()
{
    qDebug() << "Versuche Verbindung zum Server aufzubauen";
    socket->connectToHost(QHostAddress("192.168.0.151"), 6789, QIODevice::WriteOnly);
}

void Client::connectionToServerIsDone()
{
    if( socket->isValid() )
    {
        connectionTimer->stop();
        QByteArray data;
        QFile file( QString("/tmp/%1.txt1").arg(id) );
        if(!file.open(QIODevice::ReadOnly))
        {
            qDebug() << "Datei konnte nicht gelesen werden";
            return;
        }
        data = file.readAll();
        file.close();
        int size = socket->write(data);
        qDebug() << "gesamt geschrieben " << size << " Bytes";
        socket->flush();
        socket->disconnectFromHost();
    }
}
Zuletzt geändert von ms47 am 29. März 2010 13:09, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Warum sollte es nicht funktionieren? Da Du sofort auf newConnection() reagierst wird die erste pendingConnection sofort aus der Qt-Queue entfernt und erst danach kommt die zweite. Aber in der Qt-Queue ist dann ja keine mehr, also passt die Doku.

Zum anderen Problem - dafür gibt es eigentlich nur eine Lösung - so wie es auch in der Doku steht. Ein Worker-Object pro eingehende Verbindung und nicht alles innerhalb des Servers handeln.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
ms47
Beiträge: 35
Registriert: 22. Januar 2009 10:02

Beitrag von ms47 »

Christian81 hat geschrieben:Warum sollte es nicht funktionieren? Da Du sofort auf newConnection() reagierst wird die erste pendingConnection sofort aus der Qt-Queue entfernt und erst danach kommt die zweite. Aber in der Qt-Queue ist dann ja keine mehr, also passt die Doku.
Hmm, wenn man das so betrachtet, dann stimmt das natürlich. Die Sichtweise ist mir aber gar nicht in den Sinn gekommen :-) also Danke für die Hilfestellung
Christian81 hat geschrieben: Zum anderen Problem - dafür gibt es eigentlich nur eine Lösung - so wie es auch in der Doku steht. Ein Worker-Object pro eingehende Verbindung und nicht alles innerhalb des Servers handeln.
Da hatte ich ja gehofft, mir die Arbeit ersparen zu können, indem ich von vornherein nur eine Verbindung zulasse (allein auch von der Geschwindigkeit her soll das so sein).

Aber ich habe mir jetzt so geholfen:
direkt nach der ersten Verbindung schliesse ich den Server (close()) und nach der erfolgreichen Übertragung horche ich wieder auf eingehende Verbindungen (listen()). Da eh nur eine Verbindung da sein darf, ist das die wenigste Arbeit.

Danke und Gruß
Markus
Antworten