server (2288B)
1 #!/usr/bin/perl 2 3 use strict; 4 use Socket; 5 use POSIX; 6 7 # Verbose messaging 8 sub msg { 9 # print STDERR ("server: ", @_); 10 } 11 12 # Child process catcher 13 sub reaper { 14 while ((my $waitedpid = waitpid(-1,WNOHANG)) > 0) { 15 msg ("Child $waitedpid done", 16 ($? ? " with exit $?" : ''), 17 "\n"); 18 } 19 $SIG{CHLD} = \&reaper; 20 } 21 22 # Connection handler 23 sub handleconnection () { 24 my $pid; 25 26 # Daemonize 27 if (!defined ($pid = fork())) { 28 msg ("Can't fork: $!\n"); 29 return; 30 } elsif ($pid) { 31 # Parent branch 32 msg ("Connection handler started as pid $pid\n"); 33 return; 34 } 35 36 # Child branch 37 while (defined (my $line = <Client>)) { 38 chomp ($line); 39 $line =~ s/\r//; 40 last if ($line eq ''); 41 msg ("Client says: [$line]\n"); 42 } 43 44 msg ("Sending response\n"); 45 my $msg = "Hello World!\n"; 46 print Client ("HTTP/1.0 200 OK\r\n", 47 "Content-length: ", length($msg), "\r\n", 48 "\r\n", 49 $msg); 50 exit (0); 51 } 52 53 # Daemon server 54 sub serve ($) { 55 my $port = shift; 56 57 # Create the tcp service. 58 socket (Server, PF_INET, SOCK_STREAM, getprotobyname ('tcp')) 59 or die ("Can't create server socket: $!\n"); 60 setsockopt (Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) 61 or die ("Can't set socket options: $!\n"); 62 bind (Server, sockaddr_in ($port, INADDR_ANY)) 63 or die ("Can't bind to port: $!\n"); 64 listen (Server, SOMAXCONN) 65 or die ("Can't listen to socket: $!\n"); 66 msg ("Server started on port $port.\n"); 67 68 $SIG{CHLD} = \&reaper; 69 $SIG{INT} = sub { 70 msg ("Interrupt caught, terminating..\n"); 71 exit(0); 72 }; 73 74 while (1) { 75 for (my $waitedpid = 0; 76 (my $paddr = accept (Client, Server)) || $waitedpid; 77 $waitedpid = 0, close (Client)) { 78 next if ($waitedpid and not $paddr); 79 my ($port, $iaddr) = sockaddr_in ($paddr); 80 my $name = gethostbyaddr ($iaddr, AF_INET); 81 82 msg ("Connection from $name/", inet_ntoa ($iaddr), ":$port\n"); 83 84 handleconnection (); 85 } 86 } 87 } 88 89 # Main starts here 90 if ($#ARGV != 1) { 91 die <<"ENDUSAGE"; 92 93 Usage: server nsec portnr 94 95 ENDUSAGE 96 } 97 98 alarm (shift (@ARGV)); 99 serve (shift (@ARGV)); 100