# TinyWebServer **Repository Path**: bycheng/TinyWebServer ## Basic Information - **Project Name**: TinyWebServer - **Description**: 基于c++实现TinyWebServer - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2023-01-31 - **Last Updated**: 2023-01-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README TinyWebServer =============== * **项目简介**:此项目是基于Linux的轻量级多线程Web服务器,可以实现上万的并发连接数据交换。 **主要工作**: - 主要实现了浏览器的账号登录和注册,同时可以访问服务端图片文件等数据,利用MySQL存储账户名和密码; - 利用Epoll技术,实现Reactor和Proactor两种事件处理模式,完成对读写数据、接受新连接及处理客户请求的处理; - 利用数据库连接池、线程池、内存池提供服务,增加并行服务数量和服务器性能; - 利用升序链表实现定时器容器,对定时事件统一管理,同时使用SIGALRM信号定时删除非活跃的定时事件; - 实现异步日志系统,记录服务器运行状态。 # **框架** ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/1.png) # **内存池** 为每一个线程建立内存池,内存池使用链表进行管理,小于64K往内存池申请,大于64K往系统申请,具体可看memorypool文件夹 ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/memorypool.png) # **内存池-改进** ​ 将内存划分为大小为4KB的内存块,为每一内存块赋予一个内存ID,用基数树存储内存ID和管理该内存的指针,同时以三层结构进行管理,每一层各自使用数组和链表进行内存的管理;具体可看concurrent_memorypool文件夹 - 第一层为线程缓存,为每一个线程独占,用于小于64KB内存的分配; - 第二层为中心缓存,为所有线程共享,第一层线程缓存不足时可向第二层申请内存; - 第三层为页缓存,页缓存是在中心缓存上面的一层缓存,存储的内存是以页为单位存储及分配,中心缓存不足时需要从页缓存分配 出一定数量的内存块。 ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/concurrent_memorypool_0.png) 第一层 ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/concurrent_memorypool_1.png) 第二层 ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/concurrent_memorypool_2.png) 第三层 ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/concurrent_memorypool_3.png) # **线程池** ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/threadpool.png) 1.最简单方法利用STL的队列,然后多个线程竞争队列中的任务,每次往队列存取任务时,利用互斥锁完全锁住整个队列。 ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/queue.png) 2.方法1锁的颗粒度太大了,会影响并发性能。因此可自己利用链表实现一个线程安全的队列,只需要维护链表头和尾部节点,同时使用两个互斥锁(头锁锁头节点和尾锁锁尾节点)和一个条件变量,每次从尾部插入任务,头部取出数据;具体可看代码queue_lock_headAndtail.h ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/queue_head_tail.png) 3.还可以可自己利用链表实现一个线程安全的队列,利用无锁编程实现线程安全的队列,具体可看queue_freelock.h # **日志+阻塞队列** ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/blocakqueue.png) # **数据库连接池** - 连接池只需要一个实例,所以connection_pool以单例模式设计; - 从connection_pool中可以获取和Mysql的连接; - 空闲连接Mysql全部维护在一个线程安全的链表中,含有最大连接数maxsize,初始化时先往链表中放入maxsize个节点; - 连接的生产和连接的消费采用生产者-消费者线程模型来设计,使用两个互斥锁(头锁和尾锁)和一个条件变量保证链表的线程安全,从队头取数据,队尾插入数据。 ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/mysqlpool.png) # 定时器方案 ![](https://gitee.com/caoguangjing/TinyWebServer/raw/master/image/list_time.png) # 快速运行 * 服务器测试环境 * Ubuntu版本16.04 * MySQL版本5.7.29 * 浏览器测试环境 * Windows、Linux均可 * Chrome * FireFox * 其他浏览器暂无测试 * 测试前确认已安装MySQL数据库 ```C++ // 建立yourdb库 create database yourdb; // 创建user表 USE yourdb; CREATE TABLE user( username char(50) NULL, passwd char(50) NULL )ENGINE=InnoDB; // 添加数据 INSERT INTO user(username, passwd) VALUES('name', 'passwd'); ``` - 修改main.cpp中的数据库初始化信息 ```c++ //数据库登录名,密码,库名 string user = "root"; string passwd = "root"; string databasename = "yourdb"; ``` build ``` sh ./build.sh ``` - 启动 ```c++ ./server ```