MiniWebServer
BlitzMax Forums/BlitzMax Programming/MiniWebServer
| ||
This is a mini webserver I am hoping to run online sometime. Run the following in the same folder as an index.html file and then launch a webbrowser to localhost:4663 which is the same port as googledesktop but they don't seem to mind each other. I'm going to start compiling BlitzMax CGI programs on my remote account first which is another topic but would like to keep developing the following so if anyone wants to help, I need some sort of session manager code that looks after cookies etc. I'll probably look at support for standard CGI-bin process launching next. A web front end for the miniwebserver user interface would also be good, perhaps it could listen on another port and allow you to do session control stuff from the browser, sync files, show stats etc. ' minwebserver.bmx Strict Local socket:TSocket=CreateTCPSocket() BindSocket socket,4663 SocketListen socket Print "listening on port 4663" While True Local client:TSocket=SocketAccept(socket,20) If client New TConnection.Create(client) TConnection.PollAll ' Print "poll" Wend End Type TConnection Global connections:TList=New TList Field id Field _socket:TSocket Field _stream:TStream Field _data$ Method getline$() Local p,l$ p=_data.find("~n") If p=-1 p=_data.length l=_data[..p] _data=_data[p+1..] Return l End Method ' Method WritePage() Method ServePage(uri$) Local file$,size,p Print "serving "+uri+" from connection#"+id If uri$="/" file="index.html" Else file=uri If file[..1]="/" file=file[1..] p=file.find("?") If p>0 file=file[..p] ' file=uri[..p] ' uri=args[p..] EndIf If file And FileType(file)=FILETYPE_FILE size=FileSize(file) If size=0 Print "ServePage "+uri+" is empty" Return EndIf WriteLine _stream,"HTTP/1.1 200 OK" WriteLine _stream,"Content-Type: text/html; charset=UTF-8" WriteLine _stream,"Content-Length: "+size WriteLine _stream,"Pragma: no-cache" WriteLine _stream,"Expires: Fri, 01 Jan 1990 00:00:00 GMT" WriteLine _stream,"Cache-control: no-cache, no-store, must-revalidate" WriteLine _stream,"Connection: keep-alive" WriteLine _stream,"Keep-Alive: 30000" WriteLine _stream,"" WriteLine _stream,LoadText(file) ' DebugLog file+" sent" Else DebugLog "Failed To find file "+file EndIf ' debuglog "Served!" End Method Field getname$ Method Poll() Local bytes,mess$ bytes=SocketReadAvail(_socket) If bytes _data:+ReadString(_stream,bytes) EndIf While _data mess=Trim(getline()) ' Print "*"+mess If mess[..4]="GET " getname=mess[4..] getname=getname.replace(" HTTP/1.1","") EndIf If mess="" If getname ServePage getname getname="" Else Print "blank line unknown!" EndIf Else 'If getname="" Print "$"+mess+"$" 'Print mess EndIf Wend End Method Method Create:TConnection(client:TSocket) Print "creating connection!" _socket=client _stream=CreateSocketStream(client) connections.AddLast Self id=connections.count() Return Self End Method Function PollAll() Local connect:TConnection For connect=EachIn connections connect.Poll Next End Function End Type |
| ||
Hey skid - works really well on the local. Should this work across a local network? Tried accessing from another PC, the server advises 'serving / HTTP/1.0 from connection#1, but the PC is stuck on opening page. This is on my work network (which could be locked down somewhere), I'll give it a try on our testlab network shortly. |
| ||
You crazy. |
| ||
What Michael said. A non-threaded webserver simply doesn't have the performace to be generally useful. Use Lighttpd instead. |
| ||
Hmmm... If that statement about multithreading would be true, then I wonder how the old Unix servers were able to deliver in the times when Unix (including Linux) did not support multithreading? Were they spawning new processes for every new connection? |
| ||
I wonder how the old Unix servers were able to deliver in the times when Unix (including Linux) did not support multithreading? Pre-1970's Unix systems where not operated as servers. |
| ||
But you do know that Linux only in 1998+/- began to have multithreading support? Until then, it only had multitasking capabilities, but was very well used as a server. And what about sendmail? If I am not mistaken, it also is not multithreaded. Postfix is, but not sendmail. Neither are some of the older Usenet NNTP servers, e.g. I think my original question is valid: If you don't have multitasking, how do you write a working server? Obviously, it -is- possible. And must be - after all sooner or later things must be serialized, and if it's just for the hardware access. |
| ||
Actually it works just as well by asking connections if they have any data. Multithreading usually occurs controlled on servers (thread pool) since just spawning a process for each connection can easily kill the server :) |
| ||
Yes, it would be quite easy to bring a server to its knees with that approach. :) Well, I'll go on with the SocketReadAvai() approach then. |
| ||
Skidserver worked well here, received the following results: Building skidserver Compiling:skidserver.bmx flat assembler version 1.66 3 passes, 7408 bytes. Linking:skidserver.exe Executing:skidserver.exe listening on port 4663 creating connection! serving / from connection#1 I'm off to analyse the code now to see what I can learn from it - being a noob to server-ing in BMax.... |
| ||
If you don't have multitasking, how do you write a working server? If you're using a proper OS, use Inetd. Which would probably be the prefered solution in this case aswell, so you don't have to do all the socket handling but can just use stdio. |
| ||
Thanks, FlameDuck, that opens a new perspective. On OS X, this now would be xinetd instead of inetd, if I'm not wrong. I guess I'll take a closer look at this. :) |
| ||
Oh, I'm now reading that on Tiger, launchd also replaced xinetd. They seem to change things rather quicky. :) |
| ||
on the security side, you can download the server app by specifying it's name. *EDIT* forgot to add... cool :) I might tinker with this if I can get some time (at christmas maybe). |