【C++实现HTTP服务器项目记录】服务器

一、服务器基本框架

服务器基本框架主要由I/O处理单元,逻辑单元和网络存储单元组成,其中每个单元之间通过请求队列进行通信,从而协同完成任务。

服务器基本框架

模块 功能
I/O处理单元 处理客户端连接,读写网络数据。
逻辑单元 处理业务逻辑。
网络存储单元 本地数据库和文件等。

二、IO模型

IO模型

三、两种高效的事件处理模式

1. Reactor模式

- 主线程(I/O处理单元)只负责监听文件描述符上是否有事件发生,有的话立即通知工作线程(逻辑单元),读写数据、接受新连接及处理客户请求均在工作线程中完成。通常由同步I/O实现。

Reactor模式

2. Proactor模式

- 主线程(I/O处理单元)和内核负责处理读写数据、接受新连接等I/O操作,工作线程(逻辑单元)仅负责业务逻辑,如处理客户请求。通常由异步I/O实现。

Proactor模式

四、并发编程模式 – 半同步/半异步模式

- 同步线程用于处理客户逻辑,异步线程用于处理I/O事件。
- 异步线程监听到客户请求后,就将其封装成请求对象并插入请求队列中。
- 请求队列将通知在同步模式下工作线程来读取并处理该请求对象。

五、IO多路复用

IO多路复用

补充:一个线程读取某个Socket上的数据后开始处理数据,在处理过程中该Socket上又有新数据可读,另一个线程被唤醒读取,此时出现两个线程处理同一个Socket。我们期望一个Socket连接在任一时刻都只被一个线程处理,通过对该文件描述符注册EPOLLONESHOT事件,令一个线程处理socket时,其他线程将无法处理。当该线程处理完后,需要重置EPOLLONESHOT事件。

六、代码实现

1.webserver.h

#ifndef WEBSERVER_H
#define WEBSERVER_H

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <cassert>
#include <sys/epoll.h>

#include "./threadpool/threadpool.h"
#include "./http/http_conn.h"

// 最大文件描述符
const int MAX_FD = 65536;
// 最大事件数
const int MAX_EVENT_NUMBER = 10000;
// 最小超时单位
const int TIMESLOT = 5;

class WebServer
{
   
public:
    // 构造函数
    WebServer();
    // 析构函数
    ~WebServer();
    // 初始化部分成员属性
    void init(int port, string user, string passWord, string databaseName,
              int log_write, int opt_linger, int trigmode, int sql_num,
              int thread_num, int close_log, int actor_model);

    void thread_pool();
    void sql_pool();
    void log_write();
    // 设置监听与通信文件描述符触发模式
    void trig_mode();
    void eventListen();
    void eventLoop();
    void timer(int connfd, struct sockaddr_in client_address);
    void adjust_timer(util_timer *timer);
    void deal_timer(util_timer *timer, int sockfd);
    bool dealclinetdata();
    bool dealwithsignal(bool &timeout, bool &stop_server);
    void dealwithread(int sockfd);
    void dealwithwrite(int sockfd);

public:
    /******基础******/
    // 服务器端口
    int m_port;
    // root文件夹的路径
    char *m_root;
    // 日志写入方式
    int m_log_write;
    // 是否关闭日志
    int m_close_log;
    // 并发模型选择
    int m_actormodel;

    int m_pipefd[2];
    int m_epollfd;
    // HTTP对象数组指针
    http_conn *users;

    /******数据库相关******/
    // 数据库连接池对象
    connection_pool *m_connPool;
    // 登录数据库用户名
    string m_user;
    // 登录数据库密码
    string m_passWord;
    // 使用数据库名
    string m_databaseName;
    // 数据库连接池数量
    int m_sql_num;

    /******线程池相关******/
    // 线程池对象
    threadpool<http_conn> *m_pool;
    // 线程池内的线程数量
    int m_thread_num;

    /******epoll_event相关******/
    // 结构体数组,存储已就绪的文件描述符的信息
    epoll_event events[MAX_EVENT_NUMBER];
    // 监听文件描述符
    int m_listenfd;
    // 是否优雅关闭连接
    int m_OPT_LINGER;
    // 触发组合模式
    int m_TRIGMode;
    // 监听文件描述符触发方式
    int m_LISTENTrigmode;
    // 通信文件描述符触发方式
    int m_CONNTrigmode;

    /******定时器相关******/
    // 连接资源对象数组指针
    client_data *users_timer;
    Utils utils;
};
#endif

2.webserver.cpp

#include "webserver.h"

// 构造函数
WebServer::WebServer()
{
   
    // 创建MAX_FD个HTTP对象
    this->users = new http_conn[MAX_FD];

    // 当前工作目录的绝对路径
    char server_path[200];
    getcwd(server_path, 200);
    char root[6] = "/root";
    // 网站资源文件夹的路径
    this->m_root = (char *)malloc(strlen(server_path) + strlen(root) + 1);
    strcpy(this->m_root, server_path);
    strcat(this->m_root, root);

    // 创建MAX_FD个连接资源对象
    this->users_timer = new
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值