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). |