5.2 最小的 Perl Web 服务器

要构建一个特性完备的 HTTP 服务器,是需要做一些工作的。Apache Web 服务器的内核有超过 50 000 行的代码,那些可选处理模块的代码量更是远远超过这个数字。

这个软件所要做的就是支持 HTTP/1.1 的各种特性:丰富的资源支持、虚拟主机、访问控制、日志记录、配置、监视和性能特性。在这里,可以用少于 30 行的 Perl 代码来创建一个最小的可用 HTTP 服务器。我们来看看这是怎么实现的。

例 5-1 显示了一个名为 type-o-serve 的小型 Perl 程序。这个程序是个很有用的诊断工具,可以用来测试与客户端和代理的交互情况。与所有 Web 服务器一样,type-o-serve 会等待 HTTP 连接。只要 type-o-serve 收到了请求报文,就会将报文打印在屏幕上,然后等待用户输入(或粘贴)一条响应报文,并将其回送给客户端。通过这种方式,type-o-serve 假扮成一台 Web 服务器,记录下确切的 HTTP 请求报文,并允许用户回送任意的 HTTP 响应报文。

这个简单的 type-o-serve 实用程序并没有实现大部分的 HTTP 功能,但它是一种很有用的工具,产生服务器响应报文的方式与 Telnet 产生客户端请求报文的方式相同(参见例 5-1)。可以从 http://www.http-guide.com/tools/type-o-serve.pl 上下载 type-o-serve 程序。

例 5-1 type-o-serve——用于 HTTP 调试的最小型 Perl Web 服务器

  1. #!/usr/bin/perl
  2. use Socket;
  3. use Carp;
  4. use FileHandle;
  5. # (1) use port 8080 by default, unless overridden on command line
  6. $port = (@ARGV ? $ARGV[0] : 8080);
  7. # (2) create local TCP socket and set it to listen for connections
  8. $proto = getprotobyname('tcp');
  9. socket(S, PF_INET, SOCK_STREAM, $proto) || die;
  10. setsockopt(S, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die;
  11. bind(S, sockaddr_in($port, INADDR_ANY)) || die;
  12. listen(S, SOMAXCONN) || die;
  13. # (3) print a startup message
  14. printf(" <<<Type-O-Serve Accepting on Port %d>>>\n\n",$port);
  15. while (1)
  16. {
  17. # (4) wait for a connection C
  18. $cport_caddr = accept(C, S);
  19. ($cport,$caddr) = sockaddr_in($cport_caddr);
  20. C->autoflush(1);
  21. # (5) print who the connection is from
  22. $cname = gethostbyaddr($caddr,AF_INET);
  23. printf(" <<<Request From '%s'>>>\n",$cname);
  24. # (6) read request msg until blank line, and print on screen
  25. while ($line = <C>)
  26. {
  27. print $line;
  28. if ($line =~ /^\r/) { last; }
  29. }
  30. # (7) prompt for response message, and input response lines,
  31. # sending response lines to client, until solitary "."
  32. printf(" <<<Type Response Followed by '.'>>>\n");
  33. while ($line = <STDIN>)
  34. {
  35. $line =~ s/\r//;
  36. $line =~ s/\n//;
  37. if ($line =~ /^\./) { last; }
  38. print C $line . "\r\n";
  39. }
  40. close(C);
  41. }

图 5-2 显示了 Joe 的五金商店的管理员是如何用 type-o-serve 来测试 HTTP 通信的。

5.2 最小的 Perl Web 服务器 - 图1

图 5-2 type-o-serve 实用程序让用户输入服务器响应,将其回送给客户端

  • 首先,管理员启动了 type-o-serve 诊断服务器,在一个特定的端口上监听。由于 Joe 的五金商店已经有一个产品化的 Web 服务器在监听 80 端口了,所以管理员用下面这条命令在端口 8080(可以选择任意未用端口)上启动了 type-o-serve 服务:
  1. % type-o-serve.pl 8080
  • 只要 type-o-serve 开始运行了,就可以将浏览器指向这个 Web 服务器。在图 5-2 中,浏览器指向了 http://www.joes-hardware.com:8080/foo/bar/blah.txt

  • type-o-serve 程序收到来自浏览器的 HTTP 请求报文,并将 HTTP 请求报文的内容打印在屏幕上。然后 type-o-serve 诊断工具会等待用户输入一条简单的响应报文,后面跟着只有一个句号的空行。

  • type-o-serve 将 HTTP 响应报文回送给浏览器,浏览器会显示响应报文的主体。