■ Préalable.
- Purebasic 5.43 (Unicode) Minimum
- HTML et CSS Minimum
■ Structure du code.
- Lancement du serveur de pages HTML et affichage des connections. ( Procedure Start() )
- Préparation de l'entête HTTP ( Procedure BuildRequestHeader() )
- Traitements des pages demandées par le client* et nvoie des données au client* ( Procedure ProcessRequest() )
* Client = Navigateur
■ Démo http://109.13.115.206:6834/index.html (Open)
■ Code.
Code : Tout sélectionner
EnableExplicit
Global Title.s = "Simple Server"
Global Port = 6835
Global WWWDirectory.s = "www1/"
Global WWWIndex.s = "index.html"
Global WWWError.s = "error.html"
Global BufferSize = 1024, *Buffer = AllocateMemory(BufferSize), Buffer.s
Global ClientID
Declare Start()
Declare ProcessRequest()
Declare BuildRequestHeader(*FileContent, FileExtension.s, FileLength)
Declare ClearLog()
Declare Resize()
Declare Exit()
Start()
;Affichage / Show application
Procedure Start()
Protected ServerEvent, Result
If Not InitNetwork()
MessageRequester(Title, "Can't initialize the network !", 0)
Else
;Création du serveur / Create server
If CreateNetworkServer(0, Port)
OpenWindow(0, 0, 0, 800, 600, Title, #PB_Window_SystemMenu | #PB_Window_SizeGadget)
WindowBounds(0, 200, 100, #PB_Ignore, #PB_Ignore)
EditorGadget(0, 0, 0, 800, 560, #PB_Editor_ReadOnly)
AddGadgetItem(0, -1, FormatDate("%hh:%mm", Date()) + " | Server listening on port " + Port)
CheckBoxGadget(1, 10, 570, 200, 22, "Show Log")
SetGadgetState(1, #PB_Checkbox_Checked)
ButtonGadget(2, 700, 570, 80, 22, "Clear Log")
;Déclencheur / Trigger
BindGadgetEvent(2, @ClearLog())
BindEvent(#PB_Event_SizeWindow, @Resize())
BindEvent(#PB_Event_CloseWindow, @Exit())
Repeat
Repeat : Until WindowEvent() = 0
ServerEvent = NetworkServerEvent()
If ServerEvent
ClientID = EventClient()
Buffer = ""
Select ServerEvent
Case #PB_NetworkEvent_Data
Repeat
FreeMemory(*Buffer)
*Buffer = AllocateMemory(BufferSize)
Result = ReceiveNetworkData(ClientID, *Buffer, BufferSize)
Buffer + PeekS(*Buffer, -1, #PB_UTF8)
Until Result <> BufferSize
ProcessRequest()
EndSelect
Else
Delay(10) ; Ne pas saturer le CPU / Don't stole the whole CPU !
EndIf
ForEver
Else
MessageRequester(Title, "Error: can't create the server (port " + port + " in use ?)")
EndIf
EndIf
EndProcedure
;Demande de traitement / Process Request
Procedure ProcessRequest()
Protected RequestedFile.s, FileLength
Protected *FileContent, *Buffer
If Left(Buffer, 3) = "GET"
;Extract page html from "GET /yourpage.html HTTP/1.1"
RequestedFile = Trim(Mid(StringField(Buffer, 1, "HTTP"), 6))
If RequestedFile = ""
RequestedFile = WWWIndex
EndIf
;Mise à jour du log / UPdated log
If GetGadgetState(1) = #PB_Checkbox_Checked
AddGadgetItem(0, -1, FormatDate("%hh:%mm", Date()) + " | Client IP " + IPString(GetClientIP(ClientID)) + " load " + RequestedFile)
EndIf
;Lecture fichier demandé / Read Requested file
If ReadFile(0, WWWDirectory + RequestedFile, #PB_UTF8)
ElseIf ReadFile(0, WWWDirectory + WWWError, #PB_UTF8)
Else
MessageRequester(Title, "Error: WWW init error")
EndIf
FileLength = Lof(0)
;Initialisation Header HTTP / Init Header HTTP
*FileContent = AllocateMemory(FileLength + 200)
*Buffer = BuildRequestHeader(*FileContent, GetExtensionPart(RequestedFile), FileLength)
;Ajout contenu fichier / Add file content
ReadData(0, *Buffer, FileLength)
CloseFile(0)
;Envoyer la page HTML au client / Send the HTML page to the client
SendNetworkData(ClientID, *FileContent, *Buffer - *FileContent + FileLength)
FreeMemory(*FileContent)
EndIf
EndProcedure
;Creation entete HTTP / Create HTTP header
Procedure BuildRequestHeader(*FileBuffer, FileExtension.s, FileLength)
Protected Week.s = "Sun, Mon,Tue,Wed,Thu,Fri,Sat"
Protected MonthsOfYear.s = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"
Protected DayOfWeek.s = StringField("Sun, Mon,Tue,Wed,Thu,Fri,Sat", DayOfWeek(Date()) + 1, ",")
Protected Day = Day(Date())
Protected Month.s = StringField("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", Month(Date()), ",")
Protected Year.s = Str(Year(Date()))
Protected Time.s = FormatDate("%hh:%ii:%ss GMT", Date())
Protected ContentType.s
Protected Length
;Definition du content-type / Setup content-type
;Ref : https://fr.wikipedia.org/wiki/Type_MIME
Select LCase(FileExtension)
Case "html", "" : ContentType = "text/html"
Case "css" : ContentType = "text/css"
Case "js" : ContentType = "application/javascript"
Case "gif" : ContentType = "image/gif"
Case "jpg" : ContentType = "image/jpeg"
Case "png" : ContentType = "image/png"
Case "txt" : ContentType = "text/plain"
Case "zip" : ContentType = "application/zip"
Case "pdf" : ContentType = "application/pdf"
Default : ContentType = "application/octet-stream"
EndSelect
;Création entete / Create header
Length = PokeS(*FileBuffer, "HTTP/1.1 200 OK" + #CRLF$, -1, #PB_UTF8) : *FileBuffer + Length
Length = PokeS(*FileBuffer, "Date: " + DayOfWeek + ", " + Day + " " + Month + " " + Year + " " + Time + #CRLF$, -1, #PB_UTF8) : *FileBuffer + Length
Length = PokeS(*FileBuffer, "Server: "+ Title + #CRLF$, -1, #PB_UTF8) : *FileBuffer + Length
Length = PokeS(*FileBuffer, "Content-Length: " + Str(FileLength) + #CRLF$, -1, #PB_UTF8) : *FileBuffer + Length
Length = PokeS(*FileBuffer, "Content-Type: " + ContentType + #CRLF$ + #CRLF$, -1, #PB_UTF8) : *FileBuffer + Length
ProcedureReturn *FileBuffer
EndProcedure
Procedure ClearLog()
ClearGadgetItems(0)
EndProcedure
Procedure Resize()
Protected Width = WindowWidth(0)
Protected Height = WindowHeight(0)
ResizeGadget(0, #PB_Ignore, #PB_Ignore, Width, Height-40)
ResizeGadget(1, #PB_Ignore, Height - 30, #PB_Ignore, #PB_Ignore)
ResizeGadget(2, Width - 100, Height - 30, #PB_Ignore, #PB_Ignore)
EndProcedure
;Sortie / Exit
Procedure Exit()
CloseNetworkServer(0)
End
EndProcedure
- Enregistrer le code dans un dossier
- Créer un dossier www
- Coder la page index.html
- Coder la page error.html
- Lancer le serveur
- Coder d'autres pages.
- Laisser des commentaire ^^.