Seite 1 von 1
Monitoring-Programm / TCP oder UDP?
Verfasst: 30. März 2011 13:28
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
Verfasst: 30. März 2011 15:08
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 ...
Verfasst: 30. März 2011 18:05
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
Verfasst: 31. März 2011 12:10
von Wumpi
edit: Fragen gelöscht. So komme ich leider auch nicht weiter.
Das TCP-Problem besteht weiterhin. Bin für jeden Ratschlag dankbar.
Verfasst: 5. April 2011 15:26
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ß
Verfasst: 5. April 2011 20:16
von solarix
Entweder ich versteh die Frage falsch oder die Antwort ist tatsächlich trivial:
selbstverständlich geht das:
oder auch mit Signal:
aber eben: evt. verstehe ich auch was falsch..
BTW:
das schreibt man in ordentlichem C++ so:
sonst ist das irreführend.
hth!
Verfasst: 5. April 2011 21:03
von Wumpi
solarix hat geschrieben:
selbstverständlich geht das:
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:
Genau das hab ich gesucht. Funktioniert einwandfrei. Vielen Dank!
