Kommunikation PB Webserver <> Browser

Für allgemeine Fragen zur Programmierung mit PureBasic.
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

Kommunikation PB Webserver <> Browser

Beitrag von Micha122 »

Hallo,
dieser Code hier ist aus der Codesammlung von PureArena. Ist zwar alt, funzt aber immer noch.
Ich habe ihn lediglich um einen HTML- Link ergänzt/geändert.

Code: Alles auswählen

; German forum: http://www.purebasic.fr/german/archive/viewtopic.php?t=837&highlight=
; Author: PureFan (updated for PB3.93 by ts-soft, updated for PB4.00 by blbltheworm)
; Date: 30. April 2003
; OS: Windows, Linux
; Demo: Yes

; Beschreibung (von blbltheworm):
;    Das Beispiel erstellt einen Einfachen Webserver, der auf Anfrage ein HTML-Dokument übermittelt
;    Zum Testen einfach das Beispiel starten und mit dem Browser dann zu "http://127.0.0.1/" verbinden

EOL$ = Chr(13)+Chr(10) 

OpenConsole() 
If InitNetwork()=0 
  PrintN("Das Netzwerksystem konnte nicht initialisiert werden") 
EndIf 
If CreateNetworkServer(1,80)=0 
  PrintN("Server konnte nicht auf Port 80 erstellt werden") 
Else 
  PrintN("server wurde auf Port 80 erstellt") 
EndIf 

Repeat 
  Event= NetworkServerEvent() 
  If Event= #PB_NetworkEvent_Data
    client = EventClient() 
    
    *Buffer = AllocateMemory(1000) 
    Repeat 
      gelesen=ReceiveNetworkData(client,*Buffer,1000) 
    Until gelesen<=0 
    
    PrintN("Nachfrage von "+ IPString(GetClientIP(client))) 
     
    DatenZuSenden.s="<A href="+Chr(34)+"htm2.html"+Chr(34)+">Next</A>"
   
    
    Define HtmlFile.s
    
    HtmlFile=  "HTTP/1.1 200 OK"+EOL$
    HtmlFile+  "Date: Wed, 07 Aug 1996 11:15:43 GMT"+EOL$
    HtmlFile+  "Server: Atomic Web Server 0.2b"+EOL$
    HtmlFile+  "Content-Length: "+Str(Len(DatenZuSenden))+EOL$
    HtmlFile+  "Content-Type: text/html" +EOL$
    HtmlFile+  EOL$
    HtmlFile+  DatenZuSenden

    
    SendNetworkString(client,HtmlFile)
  EndIf 
  
ForEver

; IDE Options = PureBasic v4.00 (Windows - x86)
; Folding = -
Mein Problem ist, ich bekomme es nicht hin ein klicken auf den Link Serverseitig auszuwerten. :oops:

Ok, *Buffer enthält nach dem Klicken andere Daten als z.B. nach dem Aktualisiern des Browser.......... irgendwie finde ich da aber nichts lesbares. :oops:

Grüße, Micha
Barcodes for PureBasic - http://micha122.bplaced.net/
Andesdaf
Moderator
Beiträge: 2673
Registriert: 15.06.2008 18:22
Wohnort: Dresden

Re: Kommunikation PB Webserver <> Browser

Beitrag von Andesdaf »

Wenn ich auf den Link klicke, bekomme ich ein GET htm2.html vom Browser.
Du nicht?
Win11 x64 | PB 6.20
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

Re: Kommunikation PB Webserver <> Browser

Beitrag von Micha122 »

Wenn ich auf den Link klicke, bekomme ich ein GET htm2.html vom Browser.
Du nicht?
Genau solch eine Meldung vom Browser hätte ich gerne.
Wie bist du da rangekommen? Mit ReceiveNetworkData und *Buffer?

Rein kommt am Server ja was , insgesamt 322 Byte bei jeden Klick auf den Link.
Nur was mache ich nun mit den Bytes, bzw. wie lese ich die??

Debug PeekS(*Buffer) egal welche Kodierung ich benutze bringt nur merkwürdige Zeichen hervor.
Sieht irgendwie asiatisch aus. :?
Barcodes for PureBasic - http://micha122.bplaced.net/
Andesdaf
Moderator
Beiträge: 2673
Registriert: 15.06.2008 18:22
Wohnort: Dresden

Re: Kommunikation PB Webserver <> Browser

Beitrag von Andesdaf »

Hast du den Unicode-Modus in den Compiler-Optionen eingeschaltet? Dann brauchst du

Code: Alles auswählen

Debug PeekS(*Buffer, -1, #PB_UTF8)
Win11 x64 | PB 6.20
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

Re: Kommunikation PB Webserver <> Browser

Beitrag von Micha122 »

Verdammt, UNICODE >_<
Hatte schon öfter Huddel damit bzw. vergesse das öffter mal gerne. :oops:
Werde wenns fertig trotzdem mal nen bisschen Code hier posten.

So gefällt mir die Ausgabe:
GET /htm2.html HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://localhost/htm2.html
Connection: keep-alive
DANKE!
Barcodes for PureBasic - http://micha122.bplaced.net/
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

Re: Kommunikation PB Webserver <> Browser

Beitrag von Micha122 »

So, ich habe mit dem PB Webserver nun mal ein wenig weitergemacht.
Mein Anwendung ist da doch sehr spezifisch, deshalb erst mal ein paar Erläuterungen.

Ich bastle momentan an einer WebGUI universell einsetzbar mit jedem Mikrocontroller der seriell mit dem PC kommunizieren kann.

Dies geschieht folgendermaßen:
HTML z.B. mit NVU erstellen und Platzhalter

Code: Alles auswählen

<!--placeholder1-->
bis

Code: Alles auswählen

<!--placeholder100-->
an gewünschter stelle ins HTML einfügen. Die Platzhalter werden beim senden der Seite durch Content den der µC sendet ersetzt.
Umgekehrt werden Events der Gadgets/Form an den µC gesendet.
Leider habe ich aber bezüglich Server - Browser Kommunikation noch nicht alles hinbekommen. >_<

Habe nun einfach mal für Euch ein kleines Demo vorbereitet.
Demonstration deshalb, weil ich nun mal nicht davon ausgehe, das jeder Leser hier mal gerade so nen Mikrocontroller zu Hand hat um den tatsächlichen Code zu testen.
Den ganzen Serial- Code habe ich entfernt und durch zwei Dummy Prozeduren ersetzt.
Ok, durch das ganze Ausschneiden werde ich nun leider keinen Code Schönheitswettbewerb gewinnen, aber egal. :D

Hier nun der PB Code und zwei HTML.
In Eurem PB Code Verzeichnis müsst Ihr einen Ordner namens "Server_Content" erstellen. Dort kommen logischerweise die zwei HTML Dateien rein.

PB Code:

Code: Alles auswählen

;          UNICODE PB 5.42 LTS Window x86

EnableExplicit

Declare content_html(client,*Buffer)                 ;Sendet alle notwendigen Daten zum Browser
Declare.s MC_Daten_anfordern(placeholder_number)     ;Soll später mal Daten seriell vom Mikrocontroller empfangen. DERZEIT NUR EIN DUMMY
Declare.s MC_Daten_senden(command.s)                 ;Soll später mal Befehle seriell zum Mikrocontroller senden. DERZEIT NUR EIN DUMMY

Define *Buffer
Define Event
Define client
Global Dim placeholder.s(100)
Global An_Aus.s = "An"                               ;wird nur für die Dummy Prozeduren gebraucht zwecks Demo

OpenConsole()
If InitNetwork()=0
  PrintN("Das Netzwerk konnte nicht initialisiert werden")
  End
EndIf
If CreateNetworkServer(1,80)=0
  PrintN("Server konnte nicht auf Port 80 erstellt werden")
  End
Else
  PrintN("Server wurde auf Port 80 erstellt")
EndIf

*Buffer = AllocateMemory(1000) ;Speicher für den HTML Content. Derzeit 1000 Bytes

Repeat
  Event= NetworkServerEvent()
  Select Event
    Case #PB_NetworkEvent_Data 
      client = EventClient() 
      PrintN("Nachfrage von "+ IPString(GetClientIP(client)))
      ;TODO: Server Log- Datei zum speichern der IP
      content_html(client,*Buffer)
  EndSelect
ForEver



Procedure content_html(client,*Buffer)
  
  Define bytes_gelesen
  Define HtmlFile.s
  Define content_laenge
  Define content.s
  Define EOL$ = Chr(13)+Chr(10)
  Define Request.s
  Define info.s
  Define zaehler
  Define Replace_placeholder.s
  
  FillMemory(*Buffer,1000)
  
  Repeat
    bytes_gelesen=ReceiveNetworkData(client,*Buffer,1000)
  Until bytes_gelesen<=0
  Request.s = PeekS(*Buffer,-1,#PB_UTF8)
  ;TODO: Request im Server-Log protokollieren
  
  If StringField(Request.s,1,"/") = "POST "
    MC_Daten_senden(Request.s)
  EndIf
  
  info.s = StringField(Request,2,"/")
  info.s = RemoveString(info.s," HTTP")
  
  If info.s=""
    info.s="index.html"
  EndIf
  
  If info="favicon.ico"  ;wird derzeit noch nicht unterstützt
                         ;TODO: favicon Unterstützung
    ProcedureReturn 
  EndIf
  
  ;HTML laden und Platzhalter im Content ersetzen
  If ReadFile(0,"Server_Content\"+info.s,#PB_File_SharedRead)
    While Eof(0) = 0
      content.s + ReadString(0,#PB_UTF8)+EOL$
    Wend
    CloseFile(0)
    For zaehler = 1 To 100
      Replace_placeholder.s = MC_Daten_anfordern(zaehler)
      content.s = ReplaceString (content.s,"<!--placeholder"+Str(zaehler)+"-->",Replace_placeholder)
    Next zaehler
    content_laenge = StringByteLength(content.s,#PB_UTF8)
  EndIf
  
  ;HTTP Header und Seiten-Content senden
  HtmlFile=  "HTTP/1.1 200 OK"+EOL$
  HtmlFile+  "Date: Wed, 07 Aug 1996 11:15:43 GMT"+EOL$
  HtmlFile+  "Server: Atomic Web Server 0.2b"+EOL$
  HtmlFile+  "Content-Length: "+Str(content_laenge)+EOL$
  HtmlFile+  "Content-Type: text/html" +EOL$
  HtmlFile+  EOL$
  HtmlFile+  content.s
  
  SendNetworkString(client,HtmlFile)
  
  
EndProcedure


Procedure.s  MC_Daten_anfordern(placeholder_number) 
  ;FIXME: Diese Prozedur ist nur ein Dummy für serielle Kommunikation mit einem Mikrokontroller
  Define ReturnString.s
  
  
  placeholder(1) ="40%"
  placeholder(2) =Str(Random(70,30))+"%"
  placeholder(3) =Str(Random(70,30))+"%"
  placeholder(4) =Str(Random(70,30))+"%"
  placeholder(5) = An_Aus.s
  
  If placeholder(placeholder_number) <>""
    ReturnString.s = placeholder(placeholder_number)
  EndIf
  
  ProcedureReturn ReturnString.s
EndProcedure


Procedure.s MC_Daten_senden(command.s)
  ;FIXME: Diese Prozedur ist nur ein Dummy für serielle Kommunikation mit einem Mikrokontroller
  Define Send_Serial.s
  Define sl
  
  Send_Serial.s = StringField(command.s,2,";;")
  sl = StringByteLength(Send_Serial.s) /2-2
  Send_Serial=Left(Send_Serial,sl)
  PrintN("Es wird "+Send_Serial.s+" an den Mikrocontroller gesendet. Wenn das Programm mal fertig ist. ;-)")
  
  Select Send_Serial.s
    Case "ja=Wassersparprogramm AN"
      An_Aus.s = "AN"
    Case "nein=Wassersparprogramm AUS"
      An_Aus.s = "AUS"
  EndSelect
  
  
EndProcedure
Html bitte als "index.html" im Content Ordner speichern:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="content-type">
<title>Mikrocontroller Projekt Gartenbew&auml;sserung</title>
</head>
<body>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;<big><big><span
style="font-weight: bold;">Mikrocontroller Projekt
Gartenbew&auml;sserung DEMO</span></big></big><br>
<br>
Die Button Events werden auch in der Console angezeigt!<br>
<br>
&nbsp;F&uuml;llstand Zisterne:&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<!--placeholder1-->
&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>
<br>
&nbsp;Bodenfeuchte Messpunkt 1:&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;<!--placeholder2-->&nbsp;
&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>
&nbsp;Bodenfeuchte Messpunkt 2:&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;
&nbsp; &nbsp;<!--placeholder3-->
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>
&nbsp;Bodenfeuchte Messpunkt 3:&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp;<!--placeholder4--> <br>
<br>
&nbsp;Wassersparprogramm :&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp;
<!--placeholder5--><br>
<br>
<br>
<form enctype="text/plain" target="_self" method="post"
action="/" name="Wasser_sparen_ja"><input
name=";;ja" value="Wassersparprogramm AN" type="submit"><br>
</form>
<form target="_self" enctype="text/plain" method="post"
action="/" name="Wasser_sparen_nein"><input
name=";;nein" value="Wassersparprogramm AUS"
type="submit"><br>
</form>
<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;<a href="demo2.html"><big>weiter
zur nur n&auml;chsten Demo</big></a><br>
<br>
<br>
<br>
<br>
<br>
<br>
</body>
</html>
HTML2 als bitte als "demo2.html" in den Content Ordner.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="content-type">
<title>Universal Mikrocontroller WebGUI</title>
</head>
<body>
<big>Ein wenig Spielerei :-)</big><br>
<br>
Events werden auch hier wieder iim Consolenfenster angezeigt<br>
<br>
<form enctype="text/plain" method="post"
action="/demo2.html" name="test"> <input
name=";;text"><br>
</form>
<br>
<form enctype="text/plain" method="post"
action="/demo2.html" name="test1"><input
name=";;checkbox" type="checkbox"><br>
<input value="checkbox Senden" name=";;senden"
type="submit"><br>
<br>
</form>
<br>
<br>
<form enctype="text/plain" method="post"
action="/demo2.html" name="test1"><br>
<select size="5" name=";;Liste">
<option>soso</option>
<option>jaja</option>
</select>
<br>
<br>
<input value="Liste Senden" name=";;senden"
type="submit"><br>
<br>
<br>
<br>
<br>
</form>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</body>
</html>
Puhh, vor lauter schreiben und Einfügen habe ich gar keine Zeit mehr für meine Fragen. :lol:
Mach ich später.

Grüße
Barcodes for PureBasic - http://micha122.bplaced.net/
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

Re: Kommunikation PB Webserver <> Browser

Beitrag von Micha122 »

Das wichtigste was dem Server momentan fehlt ist ein Schutz vor ungebetenen Besuchern. :oops:
Wenn ich jetzt mal so richtig im www gelesen habe, muss ich das Rad noch nicht mal neu erfinden. :D

Der Server hat wohl die Möglichkeit im HTTP-Header ein Passwort anzufordern.
Stichwort: "Authorization: Basic"

Wie müsste der HTTP-Header aussehen, bzw. wie funktioniert das ganze?
Barcodes for PureBasic - http://micha122.bplaced.net/
Andesdaf
Moderator
Beiträge: 2673
Registriert: 15.06.2008 18:22
Wohnort: Dresden

Re: Kommunikation PB Webserver <> Browser

Beitrag von Andesdaf »

Win11 x64 | PB 6.20
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

Re: Kommunikation PB Webserver <> Browser

Beitrag von Micha122 »

Hi Andesdaf,
reicht vollkommen, diesen Artikel auf Wikipedia kannte ich auch gestern schon.
Naja, anstatt schnell zum vermuteten westlichen zu scrollen, hätte ich ich besser erst mal die Einleitung richtig gelesen. >_<
Was ich völlig überlesen habe ist ganz einfach Statuscode 401. :oops: Oder anders, habe jetzt verstanden das "WWW-Authenticate: Basic realm="RealmName"" dem Browser nur die Methode der gewünschten Authentifizierung mitteilt.

Hier noch zwei Links
https://de.wikipedia.org/wiki/HTTP-Authentifizierung Derselbe wie deiner nur in DE
https://de.wikipedia.org/wiki/HTTP-Statuscode Die erste Zeile im Server HTTP Header ist sehr wichtig. Habe ich leider erst heute gelernt.

Grüße!
Barcodes for PureBasic - http://micha122.bplaced.net/
Antworten