http服务器实现(一)

本文旨在深入学习HTTP服务器的实现,而非构建一个完全成熟的服务器。通过分析 boa 服务器源码,介绍了一个简单的服务器框架,重点讲解了select机制的工作原理和相关函数,如FD_SET、FD_ISSET等。在后续文章中,作者将逐步完善服务器功能并解析HTTP报文。
摘要由CSDN通过智能技术生成

前言

在实践的过程中,我发现,协议理解的深浅,阅读协议文档 < 看协议实现源码 < 自己实现协议的代码。
深入学习http服务器,这是本文的目的,而不是实现一个真正可用的http服务器。毕竟实现一个成熟可用http服务器的难度很大。软件都经历过很多版本的迭代,在不断测试、bug调试和完善功能的过程中,最终才变得成熟可用的。像BAT等大公司听说也是用现有的成熟框架来裁剪开发服务器的。本文参考的源码有boa服务器源码。boa源码下载
本文只是一个服务器的框架程序,在接下来的文章中,我将一步一步完善这个http服务器的功能,并把实验的成果分享出来。我想体现的是一个程序从零开发的思路,因为当面对一大坨一大坨完整的程序,有时会显得很茫然,没经验的很难体会到作者的设计意图。
多年的经验告诉我,如果想要一次性写出完美程序,那么最后就可能因为无从下手而什么都没有写。允许缺陷,开始动手吧!无论过程多么丑陋,最后也会结出经验的果实。
这是第一篇,希望自己能够坚持下去(确实写文章也需要花费很多时间)。

一、select机制

因为下文的程序框架运用到了select机制,这里有必要再回顾一下,参考我以前的博文:TCP socket select用法分析
首先,我们来看看select函数的定义和参数的含义:

int select( int nfds, fd_set FAR* readfds, fd_set * writefds, fd_set * exceptfds, const struct timeval * timeout)

参数含义:

  1. nfds:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以设置不正确。
  2. readfds:(可选)指针,指向一组等待可读性检查的套接口。
  3. writefds:(可选)指针,指向一组等待可写性检查的套接口。
  4. exceptfds:(可选)指针,指向一组等待错误检查的套接口。
  5. timeout:select()最多等待时间,对阻塞操作则为NULL。

返回值:
select()调用返回处于就绪状态并且已经包含在fd_set结构中的描述字总数;如果超时则返回0;否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError获取相应错误代码。

  1. 当返回为-1时,所有描述符集清0。
  2. 当返回为0时,表示超时。
  3. 当返回为正数时,表示已经准备好的描述符数。

select()返回后,在3个描述符集里,依旧是1的位就是准备好的描述符。这也就是为什么,每次用select后都要用FD_ISSET的原因。
select函数实现I/O多路复用,可以用来监视多个描述符,之后我们调用FD_ISSET函数确定具体是哪一个描述符准备好了。
那怎样才算准备好了呢?《unix环境高级编程》中,提到:

  1. 若对读集中的一个描述符进行的read操作不会阻塞,则认为此描述符是准备好的。
  2. 若对写集中的一个描述符进行的write操作不会阻塞,则认为此描述符是准备好的。
  3. 若对异常条件集中的一个描述符有一个未决异常条件,则认为此描述符是准备好的。
  4. 对于读、写和异常条件,普通文件的文件描述符总是认为准备好的。

操作select函数,还需要以下几个函数配合。
void FD_CLR(int fd, fd_set *set) // 清除set集合中描述符fd
int FD_ISSET(int fd, fd_set *set) //判断set集合中描述符fd是否准备好
void FD_SET(int fd, fd_set *set) //将描述符fd添加进集合set(其实是将某一位置1)。
void FD_ZERO(fd_set *set) //将set集全部清除

我们来看看下文使用到的select程序片段:

fd_set block_read_fdset;
int max_fd;
void select_loop(int server_s)
{
    FD_ZERO(&block_read_fdset);
    max_fd = server_s+1;

    while (1) {
        BOA_FD_SET(server_s, &block_read_fdset); 
        //没有可读的文件描述符,就阻塞。
        if (select(max_fd + 1, &block_read_fdset,NULL, NULL,NULL) == -1) {
            if (errno == EINTR)
          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值