基于C++的简单HTTP服务器实现

2023-05-16

基于C++的简单HTTP服务器实现
一个Web Server就是一个服务器软件(程序),或者是运行这个服务器软件的硬件(计算机)。其主要功能是通过HTTP协议与客户端(通常是浏览器(Browser))进行通信,来接收,存储,处理来自客户端的HTTP请求,并对其请求做出HTTP响应,返回给客户端其请求的内容(文件、网页等)或返回一个Error信息。

总体概述
使用线程池 + epoll(ET和LT均实现) + 模拟Proactor模式的并发模型;
使用状态机解析HTTP请求报文,支持解析GET和POST请求;
改进成小根堆实现的定时器,关闭超时的非活动连接;
利用RAII机制实现了数据库连接池,减少数据库连接建立与关闭的开销,同时实现了用户注册登录功能;
实现同步/异步日志系统,记录服务器运行状态;
改进了http_conn::write()函数,可以传输大文件;
经Webbench压力测试可以实现上万的并发连接数据交换。

具体实现

服务器测试环境

  • Ubuntu版本16.04
  • MySQL版本5.7.29
  • 火狐浏览器测试环境

测试前确认已安装MySQL数据库

// 建立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.c中的数据库初始化信息

// root root修改为服务器数据库的登录名和密码
// yourdb修改为上述创建的yourdb库名
// 3306是默认端口号
connPool->init("localhost", "root", "root", "yourdb", 3306, 8);

修改http_conn.cpp中的root路径

// 修改为root文件夹所在路径
const char *doc_root = "/home/ubuntu16/WEb/1/root";

在终端打开,生成server,启动编译

make server

启动server,port为端口号,可以指定一个如9006,12345

./server port

打开火狐浏览器

http://localhost:9006/  或者 127.0.0.1:9006

代码运行

项目并发测试 

测试方法

  • 测试环境: Ubuntu:16.04 cpu:i7-9700 内存:16G。在四种并发模式下系统运行状态
    ./test_presure/webbench-1.5/webbench -c 100 -t 10 http://ip:port/
    ./test_presure/webbench-1.5/webbench -c 1000 -t 10 http://ip:port/
    ./test_presure/webbench-1.5/webbench -c 5000 -t 10 http://ip:port/
    ./test_presure/webbench-1.5/webbench -c 10000 -t 10 http://ip:port/
    

    I/O复用方式,listenfd和connfd可以使用不同的触发模式,代码中使用LT + LT模式,可以自由修改与搭配.

  • listenfd触发模式,关闭main.c中listenfdET,打开listenfdLT
     //#define listenfdET       //边缘触发非阻塞
     #define listenfdLT         //水平触发阻塞
    
  • listenfd触发模式,关闭http_conn.cpp中listenfdET,打开listenfdLT
     //#define listenfdET       //边缘触发非阻塞
     #define listenfdLT         //水平触发阻塞
    

    connfd触发模式,关闭http_conn.cpp中connfdET,打开connfdLT

     //#define connfdET       //边缘触发非阻塞
     #define connfdLT         //水平触发阻塞
    

    测试结果

  1. LT + LT模式在这里插入图片描述
  2. LT + ET模式

    同理使用LT+ET的模式在这里插入图片描述

  3. ET+ET模式在这里插入图片描述

    日志写入方式,代码中使用同步日志,可以修改为异步写入.

同步写入日志

关闭main.c中ASYNLOG,打开同步写入SYNLOG

//#define SYNLOG //同步写日志
 #define ASYNLOG   /异步写日志

选择I/O复用方式或日志写入方式后,按照前述生成server,启动server,即可进行测试.

参考文章

https://github.com/qinguoyi/TinyWebServer/tree/raw_version
https://github.com/qinguoyi/TinyWebServer
Linux高性能服务器编程,游双著.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于C++的简单HTTP服务器实现 的相关文章

  • 是否可以将请求标头添加到 CORS 预检请求中?

    我有一个从外部服务器 不是服务器 访问 API 的网站 为网站提供服务 通过简单的XmlHttpRequest 见下文 那个API 需要将用于访问服务的 API 密钥添加为请求标头 然而 正如这些CORS https developer m
  • 尝试使用 php 发送 POST 请求,无论我做什么,我都会收到“HTTP ERROR 500”

    为了发出 HTTP 请求 有人建议我尝试使用 PHP 并给了我一段代码 url https example com dashboard api data array to gt PHONE NUMBER from gt SENDER ID
  • 如何从 Retrofit2 获取字符串响应?

    我正在做 android 正在寻找一种方法来执行超级基本的 http GET POST 请求 我不断收到错误 java lang IllegalArgumentException Unable to create converter for
  • Android httpclient文件上传数据损坏和超时问题

    我在 Android 中上传图像时遇到问题 我正在使用 apache httpmime 4 1 lib 代码是这样的 MultipartEntity reqEntity new MultipartEntity HttpMultipartMo
  • nginx上传client_max_body_size问题

    我正在运行 nginx ruby on rails 并且有一个简单的多部分表单来上传文件 一切正常 直到我决定限制要上传的文件的最大大小 为此 我设置了 nginxclient max body size to 1m 1MB 并且当该规则被
  • Zoopla 沙箱出现 cURL http 标头错误

    我正在为房地产经纪人开发代码 以通过他们的数据源将房产上传到 Zoopla 我在将所需的配置文件添加到所需的 http 标头时遇到问题 文档中唯一的示例是来自 Linux 的测试 echo branch reference test cur
  • 以 REST 方式更新整个资源集合

    我有一个资源列表的 REST URI 例如 http foo com group users 这些用户中的每一个都有一个序列号 我想公开一种方法来为集合中的所有用户重新编号这些值 并使访问该列表的每个人都可以使用此更改 由于这是对整个集合的
  • 使用 Java 通过 HTTP 下载未知长度的文件

    我想用java下载一个HTTP查询 但是我下载的文件在下载时有一个未确定的长度 我认为这将是相当标准的 所以我搜索并找到了它的代码片段 http snipplr com view 33805 http snipplr com view 33
  • HTTP请求的内容长度>正文大小

    我正在管理一个网站 该网站过去几个月在使用 MVC 3 0 ASP net 构建的 IIS 7 5 上运行良好 当我们的 AJAX POST 请求 通过 jQuery 触发 因发布的 JSON 被截断而失败时 我们时不时地会遇到一个问题 到
  • 为 REST API 编写单元测试的最佳方法是什么?

    在为 API 包装器编写单元测试时 我应该对 REST API 端点进行真正的调用 还是应该使用 mocl 响应来模拟成功和错误的调用 单元测试意味着只测试你的unit API 包装器 仅此而已 因此 不幸的是 您应该模拟整个 API 另一
  • 使用 Angularjs,$http 在 Microsoft Edge 中发布返回响应错误

    好吧 当我开发一个管理页面进行测试时 Microsoft Edge 中出现了一个奇怪的问题 这是从loginCtrl js服务器获取响应的部分源代码 http method POST url Define apiUrl admin logi
  • 是什么导致“线程被中止”异常随机发生并向浏览器显示 HTTP 标头和部分 HTML?

    发生的情况偶尔是随机的 而不是像您期望的那样将 HTML 返回到浏览器 它看起来有点像这样 线程正在中止 HTTP 1 1 200 OK 标题的其余部分 如 HTML 的 1 10 就是这样 他们实际上在浏览器窗口中收到了一堆文本 它不会一
  • Rest 和 Http 中“无状态”的含义

    当我阅读有关 REST 是什么的文档时 他们总是说 REST api 应该是无状态的 在这里 我感觉有点尴尬 因为普通的 HTTP 也是无状态的 既然REST可以说是一种使用HTTP协议的特殊架构 那么说REST应该是无状态的似乎是多余的
  • 为什么http使用CRLF作为行分隔符?

    据我所知 使用LF因为行分隔符非常流行 但我想知道为什么许多文本协议 如 HTTP FTP 使用CRLF作为它的行分隔符 我不认为这些协议是为旧打字机发明的 那么这有什么历史原因吗 我尝试通过谷歌 stackoverflow 和维基百科搜索
  • 如何在 G-WAN 中添加 HTTP/2

    我想知道是否可以通过使用解决方案 nghttp2 https nghttp2 org https nghttp2 org 很抱歉这么晚才回答 出于某种原因 Stackoverflow 没有通知我们这个问题 我之所以找到它只是因为收到了更新的
  • Angular2:动态同步http请求

    Goal 发出一系列同步 http 请求并能够将它们作为一个可观察流进行订阅 示例 不工作 let query arr test1 test2 test3 function make request query arr if query a
  • Web API GET 请求中的电子邮件地址

    我正在开发在 ASP NET Web API 中实现的 REST API 我们想要支持的一个场景是执行GET通过电子邮件地址请求一些用户信息 理想情况下 客户应该能够执行以下操作 GET api v1 users email your em
  • Django:如何测试“HttpResponsePermanentRedirect”

    我正在为我的 django 应用程序编写一些测试 在我看来 它使用 HttpResponseRedirect 重定向到其他一些网址 那么我该如何测试呢 姜戈TestCase类有一个方法assertRedirects https docs d
  • 如何在 Android 上的 HttpPost 中发送 unicode 字符

    我试图在我的应用程序中允许多语言支持 这会发出 HTTP post 来上传新消息 我需要做什么才能支持日语和其他非拉丁语语言 我的代码目前看起来像这样 note the msg string is a JSON message by the
  • 如何在PHP中完成http响应并进行进一步处理?

    就我而言 我需要向客户端回显一个标志并发送一封电子邮件 现在客户端需要等待电子邮件发送 但我想把这两个步骤分开 该怎么做呢 你可以看一下异步运行 PHP 任务 https stackoverflow com questions 858883

随机推荐