#!/usr/local/bin/pike
/* A very small threaded httpd capable of fetching files only. * Written by Fredrik Hübinette as a demonstration of Pike */
import Thread;
inherit Stdio.Port;
/* number of bytes to read for each write */
#define BLOCK 16384
/* Where do we have the html files ? */
#define BASE "/home/hubbe/pike/src/"
/* File to return when we can't find the file requested */
#define NOFILE "/home/hubbe/www/html/nofile.html"
/* Port to open */
#define PORT 1905
/* Number of threads to start */
#define THREADS 5
// There will be one of these for each thread
class worker
{
inherit Stdio.FILE : socket; // For communication with the browser
inherit Stdio.File : file; // For reading the file from disc
void create(function accept)
{
string cmd, input, tmp;
while(1)
{
socket::close(); // Close previous connection
file::close();
object o=accept(); // Accept a connection
if(!o) continue;
socket::assign(o);
destruct(o);
// Read request
sscanf(socket::gets(),"%s %s%*[\012\015 \t]",cmd, input);
if(cmd!="GET")
{
werror("Only method GET is supported.\n");
continue;
}
// Open the requested file
sscanf(input,"%*[/]%s",input);
input=BASE+combine_path("/",input);
if(!file::open(input,"r"))
{
if(!file::open(NOFILE,"r"))
{
werror("Couldn't find default file.\n");
continue;
}
}
// Copy data to socket
while(socket::write(file::read(BLOCK))==BLOCK);
}
}
};
int main(int argc, array(string) argv)
{
werror("Starting minimal threaded httpd\n");
// Bind the port, don't set it nonblocking
if(!bind(PORT))
{
werror("Failed to open socket (already bound?)\n");
return 17;
}
// Start worker threads
for(int e=1;e<THREADS;e++) thread_create(worker,accept);
worker(accept);
}
As stated in the beginning of this chapter; Pike threads are only available on some UNIX systems. The above example does not work if your system does not have threads.