Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tiny Web Server

使用Epoll进行实现的简单Web服务器

代码设计

image-20230319201257171

并行性

本项目的并行性通过线程池(Posix线程)以及epoll进行实现

执行流程

  1. 主线程执行初始化工作(配置网络、监听端口等);

  2. 主线程创建epoll实例,将需要监听的文件描述符添加到epoll的兴趣列表中;

  3. 主线程创建THREAD_NUM个线程(epollfd以及listenfd会被作为参数传递),随后主线程和子线程都将作为工作线程存在;

  4. 所有工作线程在epoll实例上调用epoll_wait函数;

  5. 当任何事件被捕捉到时,工作线程会执行下列操作:

    1. 检查fd是否为listenfd,如果是,那么对其调用accept并将connfdaccept的返回值)添加到兴趣列表中;

    2. 如果不是,那么fd就是connfd,此时可以从中读取数据。如果读取完成(检测到新的一行),那么响应此请求。否则将读取状态保存到event.data.ptr

      读取状态的定义如下:

      typedef struct HttpStatus {
          int connfd; // 连接文件描述符
          char *header; // 已读取的HTTP请求头
          size_t readn; // 已读取的字节数
          FILE *file; // 需要发送的文件
          size_t left; // 尚需发送的文件
          req_status_t req_status;
      } http_status_t;

      req_status_t被定义为:

      typedef enum REQUEST_STATUS {
          Reading,
          Writing,
          Ended
      } req_status_t;

      下一次epoll_wait接收到此fd中的事件时,服务器会继续处理此请求

    3. 请求头读取完毕之后,connfd会进入Writing状态。如果sendfile函数发送数据时触发了EAGAIN事件,同时left > 0,那么意味着写端暂时不可用。保存当前状态到HttpStatus中之后,利用EPOLL_CTL_MODconnfdEPOLLOUT | EPOLLET重新装配到epoll实例中;

About

使用Epoll进行实现的简单Web服务器

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages