Monitoring-Programm / TCP oder UDP?

Alles rund um die Programmierung mit Qt
Antworten
Wumpi
Beiträge: 7
Registriert: 30. März 2011 13:14

Monitoring-Programm / TCP oder UDP?

Beitrag von Wumpi »

Hallo zusammen,

ich versuche mich grad an einem Monitoring-Programm. Der Client ist hierbei der Monitor der die Daten anzeigt, der Server liefert die Daten eines Rechners im Netzwerk. Die konstanten Daten wie z.B. Prozessorname, Anzahl der Kerne, usw. soll einmalig übertragen werden. Variable Daten, wie z.B. die CPU-Auslastung sollen alle paar Sekunden übertragen werden.

Ich habe mir gedacht, dass ich eine TCP-Verbindung ausgehend vom Client aufbaue. Der Server sendet mir daraufhin die konstanten Daten zurück. Die variablen Daten würde ich daraufhin per UDP automatisch per Timer gesteuert vom Server senden.

Meine Frage:

Ist es sinnvoll die variablen Daten per UDP zu senden? Oder könnte ich genausogut die TCP-Verbindung aufrecht erhalten und die Daten hierüber senden?

Gruß,
Wumpi
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Generell:

UDP bietet sich an, wenn man die Flusskontrolle vom TCP nicht nutzen kann / will ...
Insbesondere, wenn man den Sendezeitpunkt von TCP nicht verzögern lassen moechte.

Wenn performance keine Rolle spielt, bzw TCP im bereich liegt, wuerd ich TCP nehmen, ganz einfach auch weil nen status der Verbindung hasst.

Manchen Admins stoesst es sicher auf, wenn fehlinformierte Programme ihre daten per UDP in die weite welt schicken, obwohl der empfaenger scho lange down ist :-)

wenn du aller sek mal 400-500 byte schickst, wirst kaum nen unterschied merken, ausser im Programmieraufwand vielleicht :-)

Ciao ...
Wumpi
Beiträge: 7
Registriert: 30. März 2011 13:14

Beitrag von Wumpi »

Danke für die Erläuterungen :). Ich denke, dann sollte ich es mal mit TCP probieren. Habe mal ein kleines Beispiel, das ich aus einem Buch entnommen habe, leicht bearbeitet. Der Client initiiert eine TCP-Verbindung und der Server schickt daraufhin die CPU-Auslastung zurück. Es wäre nun schön, wenn ich den Server dazu bringen könnte, per QTimer alle paar Sekunden die Auslastung rüberzuschicken. Wäre das in meinem Beispielprogramm leicht zu realisieren?
Hier mal der relevante Code:

Client

Code: Alles auswählen

client::client(QWidget *parent)
	: QDialog(parent)
{
	setupUi(this);
	//neuen TCP-Socket erstellen
    mytcpsock = new QTcpSocket(this);
    // Signal-Slot Verbindungen
    connect(okButton, SIGNAL(clicked()), this, SLOT(requestData()));
    connect(stopButton, SIGNAL(clicked()), this, SLOT(close()));
    connect(mytcpsock, SIGNAL(readyRead()), this, SLOT(readData()));
    connect(mytcpsock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
}

client::~client()
{

}

// Anforderung an den Server stellen
void client::requestData(){
    blockSize = 0;
    //falls in Verwendung, Socket zurücksetzen
    mytcpsock->abort();
    //mit dem Server verbinden
	mytcpsock->connectToHost(QHostAddress::LocalHost, 12345);
}

// die Antwort des Servers lesen
void client::readData(){
    QDataStream in(mytcpsock);
    in.setVersion(QDataStream::Qt_4_0);
	
	if(blockSize == 0){
        // Sind Daten zum Lesen vorhanden
        if(mytcpsock->bytesAvailable() < (int)sizeof(quint16))
            return;
        in >> blockSize;
    }
    if(mytcpsock->bytesAvailable() < blockSize)
        return;
   
	int load;
    in >> load;
	LcdNumber->display(int(load));
	
}

Server

Code: Alles auswählen

Server::Server(QWidget *parent) : QDialog(parent){

    // neuen TCP-Server erstellen
    tcpServer = new QTcpServer(this);
    // auf eingehende Verbindungen am Port lauschen
    if(!tcpServer->listen(QHostAddress::Any, 12345)){
        QMessageBox::critical(this,tr("Data-Server"),tr("Fehler beim Server: %1.").arg(tcpServer->errorString()));
        //Server schliessen
        close();
        return;
    }
    statusLabel->setText(tr("Der Server läuft an Port %1\n und wartet auf Client-Anfragen").arg(tcpServer->serverPort()));
    // Signal-Slot-Verbindungen einrichten
    connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
    // bei neuer eingehender Client-Verbindung den Slot sendData() aufrufen
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendData()));
}

void Server::sendData(){
    // die Daten werden als QByteArray gesendet
	int load;
	QTcpSocket *clientConnection;
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
	out.setVersion(QDataStream::Qt_4_0);
	
    out << quint16(0);
    // Daten für den Client erstellen
	load = getCpuLoad();
    out << load;
    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));
    // Gibt die nächste Client-Verbindung (in der Warteschlange) zurück
    clientConnection = tcpServer->nextPendingConnection();
    // Signal für den Socket einrichten, dass der unnötig belegte Speicher
    // auf der Serverseite beim Trennen der Verbindung bei Gelegenheit
    // freigegeben wird. Der Slot deleteLater ist in QObject definiert.
    connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater()));
    // die Daten (Zeit) in das Socket schreiben
    clientConnection->write(block);
    // nach getaner Arbeit den Client vom Host trennen
    clientConnection->disconnectFromHost();
}

Gruß,
Wumpi
Zuletzt geändert von Wumpi am 31. März 2011 12:10, insgesamt 1-mal geändert.
Wumpi
Beiträge: 7
Registriert: 30. März 2011 13:14

Beitrag von Wumpi »

edit: Fragen gelöscht. So komme ich leider auch nicht weiter.

Das TCP-Problem besteht weiterhin. Bin für jeden Ratschlag dankbar.
Wumpi
Beiträge: 7
Registriert: 30. März 2011 13:14

Beitrag von Wumpi »

Hallo zusammen,

das mit der TCP-Verbindung ist sogut wie gelöst. Ein Problem habe ich noch. Ich möchte einen Timer starten nachdem eine Methode ausgeführt wurde. Dieser Timer startet nach Ablauf die Methode erneut. Irgendwie hört sich es einfach an, aber ich steh grad auf dem Schlauch..

Code: Alles auswählen

mytimer = new QTimer
mytimer->setInterval(2000);
mytimer->setSingleShot(1);

connect(mytimer, SIGNAL(timeout()), this, SLOT(send()));

void Server::send(){
   ...
   ...
   ...
}

Habs mir so gedacht, wie im Code. Allerdings weiß ich nicht, wie ich den Timer starten kann.
Schön wäre sowas wie
connect(this, SIGNAL(sendbeendet()), mytimer, SLOT(start()));

Bekommt man das irgendwie hin?


Gruß
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Entweder ich versteh die Frage falsch oder die Antwort ist tatsächlich trivial:

selbstverständlich geht das:

Code: Alles auswählen

void Server::send(){
   ...
   ...
   mytimer->start(); 
} 
oder auch mit Signal:

Code: Alles auswählen

void Server::send(){
   ...
   ...
   emit sendbeendet();
} 
aber eben: evt. verstehe ich auch was falsch..

BTW:

Code: Alles auswählen

mytimer->setSingleShot(1); 
das schreibt man in ordentlichem C++ so:

Code: Alles auswählen

mytimer->setSingleShot(true); 
sonst ist das irreführend.

hth!
Wumpi
Beiträge: 7
Registriert: 30. März 2011 13:14

Beitrag von Wumpi »

solarix hat geschrieben: selbstverständlich geht das:

Code: Alles auswählen

void Server::send(){
   ...
   ...
   mytimer->start(); 
} 
Nein, die Möglichkeit hatte ich auch getestet. Führt bei mir zu einem Fehler -> Unbehandelte Ausnahme bei 0x77ad64f4....
solarix hat geschrieben: oder auch mit Signal:

Code: Alles auswählen

void Server::send(){
   ...
   ...
   emit sendbeendet();
} 
Genau das hab ich gesucht. Funktioniert einwandfrei. Vielen Dank! :)
Antworten