Linux下C++轻量级WebServer服务器 TinyWebServer(一)

主函数解析

#include "config.h"

int main(int argc,char *agrv[])
{
	//需要修改的数据库信息,登录名,密码,库名
	string user = "root";
	string pass = "123456";
	string databasename="qgydb";

	//命令行解析
	Config config;
	config.parse_arg(argc,argv);

	WebServer server;

	//初始化
	server.init(config.PORT,user,passwd,databasename,config.LOGWrite,
	            config.OPT_LINGER,config.TRIGMode,config.sql_num,config.thread_num,config.close_log,config.actor_model);
	
	//日志
	server.log_write();

	//数据库
	server.sql_pool();

	//线程池
	server.thread_pool();

	//触发模式
	server.trig_mode();

	//监听
	server.eventListen();

	//运行
	server.eventLoop();

	return 0;
}

WebServer类

重要性

WebServer类封装了服务器的主要逻辑,包括初始化、事件循环和事件处理,比较核心,所以选择看完main.cpp后看WebServer类

WebServer.h具体实现

#ifndef WEBSERVER_H
#define WEBSERVER_H
/*
包含网络编程必需的 socket/epoll 等头文件
*/
#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 <stdilb.h>
#include <cassert>
#include <sys/epoll.h>
//线程池和http处理模块
#include "./threadpool/threadpool.h"
#include "./http/http_conn.h"

const int MAX_FD = 65536;//最大文件描述符
const int MAX_EVENT_NUMBER = 10000;//epoll最大事件数
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);//接收所有配置参数进行初始化
	/*
	1.监听端口
	2.数据库用户名
	3.数据库密码
	4.数据库名
	5.日志写入方式
	6.连接关闭选项
	7.触发模式
	8.数据库连接数
	9.线程数量
	10.日志开关
	11.并发模型
	*/

	//模块初始化方法
	void thread_pool();//初始化线程池
	void sql_pool();//初始化数据库连接池
	void log_write();//初始化日志系统
	void trig_mode();//设置触发模式

	//核心网络方法
	void eventListen();//创建监听socke和epoll
	void eventLoop();//主事件循环

	//事件处理方法
	bool dealclientdata();//处理新客户端连接
	bool dealwithsignal(bool& timeout,bool& stop_server);//处理信号
	void dealwithread(int sockfd);//处理读事件
	void dealwithwrite(int sockfd);//处理写事件

	//定时器管理
	void timer(int connfd,struct sockaddr_int client_address);//创建新定时器
	void adjust_timer(utile_timer *timer);//调整定时器时间
	void deal_timer(utile_timer *timer,int sockfd);//处理超时连接

public:
	//基础
	int m_port;
	char *m_root;
	int m_log_write;
	int m_close_log;
	int m_actormodel;

	int m_pipefd[2];
	int m_epollfd;
	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

WebServer.cpp具体实现

构造函数

WebServer::WebServer()
{
	//http_conn类对象
	users=new http_conn[MAX_FD];

	//root文件夹路径
	//获取当前工作目录(系统调用)
	char server_path[200];
	//getcwd()会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数size为buf的空间大小
	getcwd(server_path,200);

	//构造根目录路径
	char root[6]="/root";
	m_root = (char *)malloc(strlen(server_path)_strlen(root)+1);//标准库内存分配
	strcpy(m_root,server_path);
	strcpy(m_root,root);

	//client_data是自定义的定时器客户端数据结构
	users_timer = new client_data[MAX_FD];//创建定时器数据数组
}

析构函数

WebServer::~WebServer()
{
	//关闭文件描述符
	close(m_epollfd);
	close(m_listenfd);
	close(m_pipefd[1]);
	close(m_pipefd[0]);

	//自定义部分
	//释放动态分配的内存
	delete[] users;//释放HTTP链接对象数组(自定义类型)
	delete[] users_time;//释放定时器数据数组(自定义类型)
	delete m_pool;//释放线程池对象(自定义模板类)

}

概念回顾

套接字(socket)的概念

  • 在网络通信过程中,需要创建一个信息的载体来进行数据的通信,这个载体我们可以称之为套接字
  • 我们可以调用函数:socket(),创建一个用于通信的套接字端点,并返回该端点对应的文件描述符
  • 在通信端点中,有两个缓冲区,分别对应发送缓冲区接受缓冲区
  • 原理图

基于TCP面向连接的通信方式

在网络通信过程中,有两种通信方式,分别是基于BS模型的,即浏览器服务器模型,和基于CS模型,即客户端服务器模型,本次项目用的是基于BS模型,但下面是CS模型

  • 通信原理图

TCP并发服务器

  • 循环服务器的模型
点击查看代码
sfd = socket();    //创建用于链接的套接字文件描述符
bind();             //绑定ip地址和端口号
listen();            //启动被动监听状态
while(1)
{
    newfd = accept();       //阻塞接受客户端连接请求
 
    //跟客户端进行数据收发
    recv();
    send();
    close(newfd);
}
close(sfd);
  • accept函数和recv函数都是阻塞函数,但是,我们想让这两个阻塞任务同时执行,互不相干扰,此时,我们就要引入并发机制:多进程、多线程、IO多路复用
posted @ 2025-06-26 18:52  北燃  阅读(175)  评论(0)    收藏  举报