基于socket编写的httpserver(perl版本200行代码)
实现的功能有:1、获取静态资源
2、目录下文件列表的显示
3、/xxx/yyy.do请求的解析
4、404、500错误处理
code:
1 #!/usr/bin/env perl 2 #tcp_socket_server.pl 3 4 use warnings; 5 use Socket; 6 use Cwd; 7 use POSIX qw(strftime); 8 use File::Spec; 9 my $port = 8080; #port 10 my $root = getcwd; 11 my %request; #save headers 12 my $mime; 13 my %mime = ( 14 "text" => "text/plain", 15 "html" => "text/html", 16 "css" => "text/css", 17 "js" => "application/javascript", 18 "json" => "application/json" 19 ); 20 my $quit = 0; 21 $SIG{INT} = $SIG{TERM} = sub { 22 $quit++; 23 exit(0); 24 }; 25 26 sub main { 27 my $argstr = join( " ", @ARGV ); #server -p8080 -r /home/toor 28 $argstr = " $argstr "; 29 if ( $argstr =~ /\s-h\s/ ) { 30 print "usage:\n"; 31 print " perl server.pl -p8080 -r /home/toor/webapp\n"; 32 exit(0); 33 } 34 if ( $argstr =~ /\s-p\s*(\d{2,5})\s/ ) { 35 $port = $1; 36 } 37 if ( $argstr =~ /\s-r\s?(\S+)\s/ ) { 38 $root = $1; 39 } 40 socket( server_socket, AF_INET, SOCK_STREAM, getprotobyname('tcp') ) 41 or die "Socket $!\n"; 42 setsockopt( server_socket, SOL_SOCKET, SO_REUSEADDR, 1 ) 43 or die "Can't set SO_REUSADDR: $!"; 44 my $my_addr = sockaddr_in( $port, INADDR_ANY ); 45 46 bind( server_socket, $my_addr ) or die "Bind $!\n"; 47 48 listen( server_socket, 5 ) || die "Listen $!\n"; 49 50 print "http server start in http://127.0.0.1:/$port\n"; 51 while ( !$quit ) { 52 accept( client_socket, server_socket ) || die "Accept $!\n"; 53 defined( $pid = fork ) || die "Fork: $!\n"; 54 if ( $pid == 0 ) { 55 &accept_request(client_socket); 56 exit(0); 57 } 58 else { 59 close(client_socket); 60 } 61 } 62 63 } 64 65 sub accept_request { # handle a request 66 # my $socket = shift; 67 &parse_headers(client_socket); #parse 68 my $uri = $request{'uri'}; 69 if(!$uri){ 70 close(client_socket); 71 return; 72 } 73 $now = strftime( "%Y-%m-%d %H:%M:%S", localtime );#my $now = `date`; # $now =~ s/\n//; 74 print "$now $request{'method'} $uri\n"; 75 $uri =~ s/(\?.*)// if($uri=~/\?.*/); 76 if ( $uri =~ /\w+\.html$/ ) { 77 $mime = $mime{'html'}; 78 } 79 elsif ( $uri =~ /\w+\.css$/ ) { 80 $mime = $mime{"css"}; 81 } 82 elsif ( $uri =~ /\w+\.js$/ ) { 83 $mime = $mime{"js"}; 84 } 85 elsif ( $uri =~ /\w+\.json$/ ) { 86 $mime = $mime{"json"}; 87 } 88 elsif ( $uri =~ /\w+\.do$/ ) { 89 $mime = $mime{"json"}; 90 my $prefix; 91 my $suffix = $uri; 92 my $refer = $request{'$Referer'}; 93 if ( $refer && $refer =~ /htmls(\/.*\/)\w+\.html/ ) { 94 $prefix = "/data$1"; 95 $suffix =~ s/\/(\w+)\.do/$1.json/; 96 $uri = "$prefix$suffix"; 97 } 98 else { 99 resp_error( 500, "Bad Request" ); 100 close(client_socket); 101 exit(1); 102 } 103 } 104 else { 105 $mime = "text/html"; 106 } 107 my $filename = File::Spec->catfile( $root, $uri ); 108 if ( -e -f $filename ) { 109 send_success($filename); 110 } 111 elsif ( -e -d $filename ) { 112 if ( -e -f "$filename/index.html" ) { 113 send_success("$filename/index.html"); 114 } 115 else { 116 resp_filelist($filename); 117 } 118 } 119 else { 120 resp_error( 404, "Not Found" ); 121 } 122 close(client_socket); 123 } 124 125 sub parse_headers { 126 127 # my ($socket) = @_; #client socket 128 my $content = ""; 129 while (1) { 130 my $buffer; 131 my $flag = sysread( client_socket, $buffer, 1024 ); 132 $content .= $buffer; 133 last if ( $flag < 1024 ); 134 } 135 if ( $content =~ m/^(.*)\s(\/.*)\s(HTTP\/\d\.\d)/ ) { 136 $request{'method'} = $1; 137 $request{'uri'} = $2; 138 $request{'protocol'} = $3; 139 } 140 my @header = split( /\n/, $content ); 141 foreach (@header) { 142 if (/^([^()<>\@,;:\\"\/\[\]?={} \t]+):\s*(.*)/i) { 143 $request{$1} = $2; 144 } 145 } 146 } 147 148 sub resp_headers { 149 print client_socket "HTTP/1.0 200 OK\n"; 150 print client_socket "Content-Type: $mime;charset: utf-8\n"; 151 print client_socket "Date: $now\n"; 152 print client_socket "Server: xyserver\n"; 153 print client_socket "\n"; 154 } 155 156 sub resp_filelist { 157 my ($directory) = shift; 158 opendir( DIR, $directory ) or die "cannot open $directory:$!"; 159 resp_headers(); 160 ( my $shortdir = $directory ) =~ s{$root}{}; 161 print client_socket 162 "<html><head><title>Index of ./</title></head><body><h1>Directory:$shortdir</h1><table border='0'><tbody>"; 163 print client_socket 164 "<tr><td><a href='../'>Parent Directory</a></td><td></td><td></td></tr>"; 165 foreach ( sort readdir DIR ) { 166 next if (/^\./); 167 my @info = stat("$directory/$_"); 168 ( my $href = "$shortdir/$_" ) =~ s/\/\//\//g; 169 $href = "$href/" if ( -d "$directory/$_" ); 170 my $size = $info[7]; 171 my $mtime = strftime( "%Y-%m-%d %H:%M:%S", localtime( $info[9] ) ); 172 $href=~ s/\/\//\//g; 173 print client_socket 174 "<tr><td><a href='$href'>$_</a></td><td style='text-align:right'>$size bytes</td><td> $mtime</td></tr>"; 175 } 176 closedir DIR; 177 print client_socket "</tbody></table></body></html>"; 178 } 179 180 sub resp_error { #status, message 181 my ( $status, $error ) = @_; 182 print client_socket "HTTP/1.0 $status $error\n"; 183 print client_socket "Content-Type: text/html;charset: utf-8\n"; 184 print client_socket "Date: $now\n"; 185 print client_socket "Server: xyserver\n"; 186 print client_socket "\n"; 187 print client_socket 188 "<html><head><title>Http Error</title></head><body><h2>Http Error...</h2><p>errror status:$status</p><pre>error message:$error</pre><hr><i><small>Powered by javaway</i></body></html>"; 189 } 190 191 sub send_success { 192 my $filename = shift; 193 resp_headers(); 194 open FILE, "<$filename" 195 or die "cannot open $filename:$!"; 196 foreach (<FILE>) { 197 print client_socket $_; 198 } 199 } 200 201 main();
github:https://github.com/x373241884y/HttpServer/tree/master/perl

浙公网安备 33010602011771号