Forum: PC-Programmierung einfacher html server mit qt?


von chris (Gast)


Lesenswert?

Hallo,

weiß jemand von euch, ob man mit qt einen html Server programmieren 
kann?
Es gibt im Tutorial Beispiele für einen UDP Server/Client und ein 
Beispiel für einen HTML Client. Aber leider kein Beispiel für einen 
Server.

Ich würde gerne mal ein wenig experimentieren und eine einfache HTML 
Seite mit dem Webbrowser darstellen.
Später soll ein Mikrocontroller Daten zum HTML Server übertragen, die 
dann im Browser dargestellt werden können.

Kann mir jemand helfen?

Gruß,
chris

von Hc Z. (mizch)


Lesenswert?

Das Protokoll, das die Daten zum Browser übertägt, heißt HTTP, nicht 
HTML.  HTML ist die Markierungssprache, mit der die Daten zur 
Darstellung formatiert werden.  Ich nehme also an, Du suchst einen 
HTTP-Server und wirst sicher leichter fündig, wenn Du danach suchst.

Was der allerdings mit QT am Hut hat (eine Library zum Aufbau von 
graphischen Bedienoberflächen), ist mir auch nicht klar.  Der 
HTTP-Server hat einfach Seiten auszuliefern und mit graphischem 
Schnickschnack wenig zu tun.

von chris (Gast)


Lesenswert?

>Der HTTP-Server hat einfach Seiten auszuliefern und mit graphischem
>Schnickschnack wenig zu tun.

Den graphischen Schnickschnack braucht man um verschiedene Einstellungen 
des Servers verändern zu können und den Datenfluss vom Mikrocontroller 
debuggen zu können.Außerdem gibt es für  qt eine hervorragend 
funktionierende Klasse für die serielle Schnittstelle, welche die 
Verbindung zum Mikrocontroller herstellt.

>Was der allerdings mit QT am Hut hat (eine Library zum Aufbau von
>graphischen Bedienoberflächen

Qt hat eine eigene Netzwerkklasse. Da ich mit qt programmiere, will ich 
diese Klasse verwenden.
Innerhalb der qt-Klassen zu bleiben hat auch den Vorteil, dass ich keine 
Probleme haben, irgendwelche inkompatiblen Libraries einbinden zu müssen 
und das Programm Plattform unabhängig bleibt.

von Rolf Magnus (Gast)


Lesenswert?

Hc Zimmerer schrieb:
> Was der allerdings mit QT am Hut hat (eine Library zum Aufbau von
> graphischen Bedienoberflächen), ist mir auch nicht klar.

Nein, Qt besteht seit Version 4.0 aus einer Sammlung von mehreren 
Libraries, von denen sich nur ein Teil um graphische Oberflächen 
kümmert.
Man kann mit Qt auch problemlos einen Server schreiben, der überhaupt 
nichts mit graphischen Oberflächen am Hut hat und nicht mal an irgendwas 
linkt, das mit graphischen Oberflächen zu tun hat.

chris schrieb:

> Qt hat eine eigene Netzwerkklasse.

Qt hat nicht nur eine "Netzwerkklasse", sondern eine ganze Bibliothek 
aus Klassen, die für Netzwerk-Kommunikation da sind.
Siehe http://doc.trolltech.com/4.6/network-programming.html

> Innerhalb der qt-Klassen zu bleiben hat auch den Vorteil, dass ich keine
> Probleme haben, irgendwelche inkompatiblen Libraries einbinden zu müssen
> und das Programm Plattform unabhängig bleibt.

HTTP setzt auf TCP auf, und um in Qt einen TCP-Server zu schreiben, 
bietet sich die Klasse (Achtung... jetzt kommt's!) QTcpServer an.

chris schrieb:
> Es gibt im Tutorial Beispiele für einen UDP Server/Client und ein
> Beispiel für einen HTML Client. Aber leider kein Beispiel für einen
> Server.

Du meinst so eins wie das:
http://qt.nokia.com/doc/solutions/4/qtservice/qtservice-example-server.html

Hast recht, das gibt es nicht ;-)

von chris (Gast)


Lesenswert?

>Du meinst so eins wie das:
>http://qt.nokia.com/doc/solutions/4/qtservice/qtse...
>Hast recht, das gibt es nicht ;-)

Hmm, das scheint tatsächlich ein Beispiel für einen HTTP-Server zu sein.

Aber nenne mich "Weichei": ich habe mich schon ein wenig an die 
Entwicklungsoberfäche "qt-creator" von qt gewöhnt. Dort findet man ein 
schönes Menü mit Beispielprogrammen. Die kann man einfach anklicken und 
mit dem grünen "Run" Button kompilieren und laufen lassen. Wunderbar, 
das ist fast so, als wenn man ein Auto, bevor man damit losfahren möchte 
gar nicht mehr zusammenschrauben müsste, sondern einfach einsteigt 
fährt. ;-)

Mit der Erstellung von Make-Files habe ich es noch nicht so. Vielleicht 
kannst Du mir einen Tipp geben wie alle Files zusammen mit der *.pro zu 
erstellen sind, damit das Programm einfach zu kompilieren ist.

Gruß,
chris

von Link zu (Gast)


Lesenswert?


von chris (Gast)


Angehängte Dateien:

Lesenswert?

Hmm, da müste ich ja qmake lernen, wo ich doch die schöne Oberfläche von 
qt-creator habe.

Jetz bin ich einfach mal so vorgegangen: In den Beispielfiles des 
qt-Creators gibt es einen TCP-Server, der sendet ein paar Sprüche bei 
einem TCP-Request.

Dort habe ich einfach den Beispielcode für "GET" aus dem obigen Link 
kopiert. Ich kann per telnet den Server kontaktieren, aber er liefert 
keine Antwort. Habt Ihr eine Ahnung warum?

von P. S. (Gast)


Lesenswert?

Nichts gegen eine schoene, angenehme Entwicklungsumgebung, aber leider 
unterstuetzen sie auch unheimlich Faulheit und erzeugen die Illusion, 
Software koennte man mit ein wenig Klickediklick entwickeln.

Tipp: Mit http://www.w3.org/Protocols/HTTP/AsImplemented.html und dich 
dann almaehlich bis zu HTTP/1.0 weiterentwickeln.

Das hier schadet sicher auch nicht: 
http://oopweb.com/CPP/Documents/DebugCPP/Volume/techniques.html

Und natuerlich noch der hier: 
http://www.amazon.de/Programmieren-C-ANSI-2-C-Reference/dp/3446154973/ref=sr_1_1?ie=UTF8&s=books&qid=1268492085&sr=8-1

von sepp (Gast)


Lesenswert?

Das hilft mir jetzt im Moment nicht weiter.

Was ich brauche ist jemand der mir sagt, warum in meinem oben geposteten 
Programm das Signal

    connect(tcpServer, SIGNAL(readyRead()), this, SLOT(sendFortune()));

meine Funktion

void Server::sendFortune() {
..}

nicht auslöst, wenn mit telnet ein Kommando an den Server gesendet wird.

Der Server selbst läuft, da man ihn mit telnet kontaktieren kann. Wird 
der Server mit dem "Quit" Button beendet, merkt das telnet und schließt 
auch ganz korrekt die Verbindung.

von chris (Gast)


Lesenswert?

>Tipp: Mit http://www.w3.org/Protocols/HTTP/AsImplemented.html und dich
>dann almaehlich bis zu HTTP/1.0 weiterentwickeln.

Wobei, der Link ist gar nicht so schlecht.

Es gibt nämlich noch ein kleines Problem: Wenn sich Web-Inhalte auf dem 
HTTP ändern ( also z.B. der Mikrocontroller einen anderen Temperaturwert 
anzeigen will ) müsste der Browser die Seite ja neu laden. Deshalb die 
Frage: Kann man den Browser dazu bringen, die Seite zyklisch 
anzufordern?

von asdfgh (Gast)


Lesenswert?

chris schrieb:
> Frage: Kann man den Browser dazu bringen, die Seite zyklisch
> anzufordern?
1
<meta http-equiv="refresh" content="50" />

zwischen <HEAD> und </HEAD> fordert zur Aktualisierung auf. Mit 
content="xy" wird die Zeit angegeben, nach der aktualisiert werden soll.

von chris (Gast)


Lesenswert?

@asdfgh

super, danke, das hilft für die Datenaktuallisierung schon mal weiter.

von chris (Gast)


Lesenswert?

Hmm, es scheint so, als wenn ich nicht der Einzige bin, der versucht hat 
das Fortune-Server Example von qt umzubauen:

http://www.c-plusplus.de/forum/viewtopic-var-t-is-250414.html

Allerdings tritt dort genau das gleich Problem auf: das Siganl 
readyRead() scheint nicht zu funktionieren.

@Rolf Magnus (Gast)
Siehst Du, genau da liegt dann das Problem: Man kann Stunden damit 
verbraten, irgend welche Fehler in Beispielen zu suchen, die eben nicht 
als lauffähige Projektdatei vorhanden sind. Das Problem liegt nämlich in 
diesem Fall jetzt nicht mehr am zusammengestückelten Code, sondern an 
irgend einer Eigenschaft von QtServer mit der auch andere Leute Probleme 
haben.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Ist zwar etwas offtopic: Aber muss man sich für einen einfachen HTTP-
Server unbedingt durch Qt udn C++ quälen? In Python, Perl oder Ruby geht
das ratzfatz ohne viel Tipparbeit. Hier ein Beispiel in Python, das die
aktuelle Uhrzeit auf einer Webseite anzeigt:
1
from BaseHTTPServer import *
2
from time import strftime
3
4
page = """
5
<html>
6
 <meta http-equiv="refresh" content="60"/>
7
 <h1>Uhrzeit</h1>
8
 Es ist jetzt %s.
9
</html>
10
"""
11
12
class MyHTTPRequestHandler(BaseHTTPRequestHandler):
13
  def do_GET(self):
14
    self.wfile.write(page % strftime("%H:%M"))
15
16
HTTPServer(("", 8080), MyHTTPRequestHandler).serve_forever()

von chris (Gast)


Lesenswert?

Du hast schon Recht: mit Python geht es einfacher.

Ich habe mir eine ganze Weile überlegt, ob Python nicht das Mittel der 
Wahl ist. Bei meinem Projekt sollte später noch Datengraph dazu kommen. 
In der Grundausstattung hat Python soweit ich das verstanden habe aber 
keine Graphik. Man muss dann erst zusätzliche Libraries installieren. 
Mein Ziel ist es aber, ein kompaktes, in sich geschlossenes Programm 
ohne große Installationsorgien zu haben.

von chris (Gast)


Lesenswert?

@Yalu X
witzig, spaßeshalber habe ich Dein Python Script mal ausprobiert und es 
kann tatsächlich die Uhrzeit im Browser anzeigen, wenn ich die lokale 
IP-Adresse eingebe:

http://192.168.1.10:8080/

Jetzt wäre es  spannend ein Python-Script, das Daten von der seriellen 
Schnittstelle einliest und im Server mit Browser-Refresh darstellt mit 
dem Aufwand in c++ zu vergleichen.

von Rolf Magnus (Gast)


Lesenswert?

sepp schrieb:

> Was ich brauche ist jemand der mir sagt, warum in meinem oben geposteten
> Programm das Signal
>
>     connect(tcpServer, SIGNAL(readyRead()), this, SLOT(sendFortune()));
>
> meine Funktion
>
> void Server::sendFortune() {
> ..}
>
> nicht auslöst, wenn mit telnet ein Kommando an den Server gesendet wird.

Das liegt ganz einfach daran, daß es dieses Signal nicht gibt, wie auch 
die Ausgabe des Programms schon sagt. Auch mit Qt wird man sich nicht 
aus Fragmenten aus völlig verschiedenen Programmen einen HTTP-Server 
basteln können, ohne auch nur einen Blick in die Doku zu werfen.
Lies wenigstens mal 
http://doc.trolltech.com/4.6/network-programming.html#using-tcp-with-qtcpsocket-and-qtcpserver

Das da ist übrigens nicht gut:
1
server.cpp: In member function ‘void Server::sendFortune()’:
2
server.cpp:148: warning: format ‘%s’ expects type ‘char*’, but argument 2 has type ‘QChar*’

Du solltest statt:
1
qDebug( "%s",tokens[0].data()   );
besser schreiben:
1
qDebug( "%s",tokens[0].toLocal8Bit().data()   );
oder nach vorherigem #include <QDebug> einfach:
1
qDebug() << tokens[0];

von chris (Gast)


Lesenswert?

Hallo Magnus,

danke für die Hinweise. Ich habe jetzt schon eine ganze Weile probiert, 
bin aber leider nicht weitergekommen.

Dafür habe ich das obige Python Beispiel für den Server erweitert ( ich 
habe bis jetzt noch nie was mit Python zu tun gehabt ).

Und ich muss sagen, es ist wirklich beeindruckend: ich konnte auf die 
Schnelle einen seriell nach http Konverter basteln. Die Daten von meinem 
Arduino Board, welche über die USB-Schnittstelle kommen, werden jetzt im 
Browser dargestellt. Das ganze funktioniert auch noch vom Rechner im 
Nachbarzimmer aus. Wenn ich die Portfreigabe im Router noch schaffe, 
dann wahrscheinlich auf der ganzen Welt ...

Hier der Code:
1
from BaseHTTPServer import *
2
from time import strftime
3
import serial
4
5
SER_PORT = '/dev/ttyUSB0'
6
SER_BAUD = 9600
7
ser = None
8
9
page = """
10
<html>
11
 <meta http-equiv="refresh" content="3"/>
12
 <h1>python serial input http server</h1>
13
 <h4>chris, march 2010 </h4>
14
 
15
 %s
16
17
</html>
18
"""
19
20
textBuffer="<p> trying serial port:" + SER_PORT + "</p>"
21
22
class MyHTTPRequestHandler(BaseHTTPRequestHandler):
23
  def do_GET(self):
24
    global textBuffer
25
    #self.wfile.write(page % strftime("%H:%M"))
26
    self.wfile.write(page % textBuffer)
27
    textBuffer=textBuffer+ser.read(10)
28
29
def cb_opendat():
30
  print "opendat"
31
32
def cb_quit():
33
  print "quit - cleanup"
34
  ser.close()
35
  root.quit()
36
37
def openSerial():
38
  global ser
39
  ser = serial.Serial(SER_PORT, SER_BAUD, timeout = 1)
40
41
openSerial()
42
43
HTTPServer(("", 8080), MyHTTPRequestHandler).serve_forever()

von Stefan (Gast)


Lesenswert?

QtWebApp ist ein HTTP 1.1 Server mit Support für Cookies, Sessions und 
Datei-Uploads.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.