Webserver项目
一. 介绍和部署
1. 介绍
Webserver是经典的C++后端服务项目,主要提供网页的客户端和服务器端数据交互
借此用于理解
- 网络编程,包括HTTP请求和响应结构,如何处理GET、POST, Socket编程、TCP/IP协议栈(连接,传输,终止)
- 多线程编程,包括线程管理、线程同步和设计模式(生产者-消费者模型)
- 数据库编程,包括SQL和NoSQLSQL,即如何使用关系数据库(MySQL)和非关系型数据库(MongoDB)进行交互
- 性能优化,包括内存的分配和释放、缓存优化
- 部署和运维,包括服务器的配置,Docker容器使用以及日志管理
掌握以下技术栈
- 线程池 + 非阻塞socket + epoll(ET和LT均实现) + 事件处理(Reactor和模拟Proactor均实现) 的并发模型
- 使用状态机解析HTTP请求报文,支持解析GET和POST请求
- 访问服务器数据库实现web端用户注册、登录功能,可以请求服务器图片和视频文件
- 实现同步/异步日志系统,记录服务器运行状态
- 经Webbench压力测试可以实现上万的并发连接数据交换
2. Linux服务器部署
首先安装ubuntu系统
版本为18.04,可以选择在虚拟机上安装,并使用vscode的ssh远程连接(具体步骤搜索vscode远程连接本地虚拟机)
虚拟机安装ssh apt-get install openssh-server
,使用远程连接可能还涉及开启和开机自启,一般来说都是默认启动,对于后面的mysql也是同样
sudo systemctl start ssh #启动
sudo systemctl enable ssh #开机自启动
sudo systemctl status ssh #检查状态
apt-get 是一个命令行工具,同样是包管理工具,用于安装和更新对应软件
进行更新sudo apt-get update
安装git apt-get install git
安装g++环境 apt-get install build-essential
安装vim apt-get install vim
代码拉取
原始版本git clone https://github.com/qinguoyi/TinyWebServer.git
中文注释版本git clone https://github.com/white0dew/WebServer.git
安装配置mysql
安装mysql sudo apt-get install mysql-server
进行配置sudo mysql_secure_installation
mysql配置包括不启用验证密码插件,设置数据库root用户密码,不删除匿名用户,禁用root用户远程登录,不删除test数据库,重新加载表权限
检测数据库状态systemctl status mysql.service
包括是否启动,以及是否开机自启,进程号等
进入数据库sudo mysql -uroot -p
初始化需要的库
create database yourdb; --创建数据库
USE yourdb; --进入数据库
CREATE TABLE user( --创建表
username char(50) NULL,
passwd char(50) NULL
)ENGINE=InnoDB;
INSERT INTO user(username, passwd) VALUES('name', 'passwd'); --插入信息
其它指令
SHOW DATABASES; --显示所有数据库
USE yourdb; --进入数据库(进入系统数据库mysql可以通过user表查询用户信息)
SHOW TABLES; --显示所有表
select *from user; --查看对应表
EXIT; --退出数据库
确保main.cpp配置和mysql数据库配置相同,这里是默认的用户
cd /etc/mysql
sudo vim debian.cnf
自定义数据库用户配置和权限
CREATE USER 'webuser'@'localhost' IDENTIFIED BY 'webpassword'; --在本地创建新用户以及对应密码
GRANT ALL PRIVILEGES ON webdatabase.* TO 'webuser'@'localhost'; --给予其相应数据库的权限
FLUSH PRIVILEGES;
执行程序
安装链接库apt-get install libmysqlclient-dev
make进行编译 sh ./build.sh
运行 ./server
具体参数
./server [-p port] [-l LOGWrite] [-m TRIGMode] [-o OPT_LINGER] [-s sql_num] [-t thread_num] [-c close_log] [-a actor_model]
-p,自定义端口号,默认9006
-l,选择日志写入方式,默认同步写入
* 0,同步写入
* 1,异步写入
-m,listenfd和connfd的模式组合,默认使用LT + LT
* 0,表示使用LT + LT
* 1,表示使用LT + ET
* 2,表示使用ET + LT
* 3,表示使用ET + ET
-o,优雅关闭连接,默认不使用
* 0,不使用
* 1,使用
-s,数据库连接数量,默认为8
-t,线程数量,默认为8
-c,关闭日志,默认打开
* 0,打开日志
* 1,关闭日志
-a,选择反应堆模型,默认Proactor
* 0,Proactor模型
* 1,Reactor模型
输入ip:9006进行登录注册
二. 各模块功能
1. 参数解析器
首先是main函数参数传入int main(int argc, char *argv[])
使用自定义Config类进行命令行参数解析,分别表示端口号,日志写入方式,触发组合模式,优雅关闭链,数据库连接池数量,线程池线程数量,是否关闭日志,并发模型选择
./server [-p port] [-l LOGWrite] [-m TRIGMode] [-o OPT_LINGER] [-s sql_num] [-t thread_num] [-c close_log] [-a actor_model]
具体解析方式采用,同时在Config类里面初始化默认参数
const char *str = "p:l:m:o:s:t:c:a:";
while ((opt = getopt(argc, argv, str)) != -1) //每次获取一个opt和一个optarg,用于判断和赋值
类似的arg使用方法,比如定义一个处理变长参数的函数
变长参数求和
#include <cstdarg>
// 定义一个处理变长参数的函数,计算所有传递参数的总和
int sum(int count, ...) {
va_list args; // 定义一个 va_list 变量,用于存储变长参数信息
va_start(args, count); // 初始化 va_list,使其指向变长参数列表的第一个参数
int total = 0;
for (int i = 0; i < count; ++i) {
total += va_arg(args, int); // 获取下一个参数,并将其累加到 total 中
}
va_end(args); // 清理 va_list 变量
return total;
}