HTTP学习笔记之二——Web服务器

目前,比较流行的Web服务器开源软件如Apache等。Web服务器的作用是接收来自客户端的请求并作出相应的响应,为客户端提供某种服务,如资源请求。

首先来看一个用perl脚本写的非常简单的Web服务程序,客户端和服务器采取socket套接字通信:

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



当然,实际的Web服务程序需要符合HTTP协议规范,远非这么简单,可以分析一个更为通用的Web服务器对来自客户端请求的响应过程如下图所示,


大致可以分为7个步骤:

(1)建立连接:如果客户端已经打开了一个与服务器的persistent connection,就可以直接使用该连接,否则需要新建一个连接。

(2)接收客户端的请求:对请求消息进行缓冲、解析处理;

(3)处理请求:对于繁忙的服务器,可能同时需要处理的连接请求成千上万个,下面会介绍服务器采取的一些架构;

(4)访问请求的资源:根据请求消息中的URL映射到服务器上某个指定的资源;

(5)创建响应;包括判断资源的MIME类型,资源长度等,以及响应是否成功或者重定向;

(6)发送响应给客户端,如果是persistent connection,响应发送完成后,仍保留连接打开状态。

(7)日志记录;


如果服务器上已经打开了若干个连接(每个连接来自不同的客户端),则服务器和这些连接连接的通信(I/O)的处理方式可以参考下图:


上面画出了4种服务器处理连接的设计:

(1)单线程I/O结构:服务器只使用一个线程按照串行的方式处理所有连接,只有当前一个连接的操作完成之后才进行下一个连接的处理;

(2)多线程I/O结构:同时创建多个线程(按需或者预先创建好一个线程池),这样支持并发的连接处理;

(3)多路复用结构:一个线程同时处理多个连接,监控所有连接的状态,当某个连接需要的数据准备好了就对它进行处理;

(4)多路复用的多线程结构:综合了多线程和多路复用的混合式结构。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值