forked from linyacool/WebServer
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
196 changed files
with
121 additions
and
7 deletions.
There are no files selected for viewing
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,36 @@ | ||
# WebServer | ||
C++ Web Server | ||
--- | ||
|
||
[](https://travis-ci.org/linyacool/WebServer) | ||
[](https://opensource.org/licenses/MIT) | ||
|
||
# A C++ High Performance Web Server | ||
|
||
## Introduction | ||
|
||
* 本项目为C++11编写的Web服务器,解析了get、post请求,可处理静态资源,支持HTTP长连接,并实现了异步日志,记录服务器运行状态。 | ||
|
||
## Envoirment | ||
* OS: Ubuntu 14.04 | ||
* Complier: g++ 4.8 | ||
|
||
## Build | ||
|
||
./build.sh | ||
|
||
## Technical points | ||
* 使用Epoll边沿触发的IO多路复用技术,非阻塞IO,使用Reactor模型 | ||
* 使用多线程充分利用多核CPU,并使用线程池避免线程频繁创建销毁的开销 | ||
* 使用基于小根堆的定时器关闭超时请求 | ||
* 主线程只负责accept请求,并以Round Robin的方式分发给其它IO线程(兼计算线程),锁的争用只会出现在主线程和某一特定线程中 | ||
* 使用eventfd实现了线程的异步唤醒 | ||
* 使用双缓冲区技术实现了简单的异步日志系统 | ||
* 为减少内存泄漏的可能,使用智能指针等RAII机制 | ||
* 使用状态机解析了HTTP请求 | ||
|
||
## Others | ||
除了项目基本的代码,进服务器进行压测时,对开源测试工具Webbench增加了Keep-Alive选项和测试功能: 改写后的[Webbench](https://github.com/linyacool/WebBench) | ||
|
||
|
||
|
||
|
||
--- | ||
|
||
[](https://travis-ci.org/linyacool/WebServer) | ||
[](https://opensource.org/licenses/MIT) | ||
|
||
--- |
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file modified
0
WebServer/tests/build/release/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake
100644 → 100755
Empty file.
Empty file modified
0
WebServer/tests/build/release/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake
100644 → 100755
Empty file.
Empty file modified
0
WebServer/tests/build/release/CMakeFiles/2.8.12.2/CMakeSystem.cmake
100644 → 100755
Empty file.
Empty file modified
0
WebServer/tests/build/release/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c
100644 → 100755
Empty file.
Empty file modified
0
WebServer/tests/build/release/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp
100644 → 100755
Empty file.
Empty file.
Empty file.
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# 测试及改进 | ||
|
||
## 测试环境 | ||
* OS:Ubuntu 14.04 | ||
* 内存:8G | ||
* CPU:I7-4720HQ | ||
|
||
## 测试方法 | ||
* 理想的测试环境是两台计算机,带宽无限,现在的网卡虽然都是千兆网卡,但是普通家用的网线都是5类双绞线,最高100Mbps,在linux下用ethtool可以看到网卡的速度被限制为100Mbsp,无法更改为更高的,经测试很容易跑满带宽,因此退而选择本地环境。 | ||
* 使用工具Webbench,开启1000客户端进程,时间为60s | ||
* 分别测试短连接和长连接的情况 | ||
* 关闭所有的输出及Log | ||
* 为避免磁盘IO对测试结果的影响,测试响应为内存中的"Hello World"字符加上必要的HTTP头 | ||
* 我的最终版本中很多方面借鉴了muduo的思路,muduo中也提供了一个简单的HTTP echo测试,因此我将与muduo进行一个小小的对比,我修改了muduo测试的代码,使其echo相同的内容,关闭muduo的所有输出及Log | ||
* 线程池开启4线程 | ||
* 因为发送的内容很少,为避免发送可能的延迟,关闭Nagle算法 | ||
|
||
|
||
## 测试结果 | ||
* WebServer短连接测试 | ||
|
||
* muduo短连接测试 | ||
|
||
* WebServer长连接测试 | ||
* muduo长连接测试 | ||
|
||
* WebServer空闲负载 | ||
* WebServer短连接CPU负载 | ||
* WebServer长连接CPU负载 | ||
|
||
|
||
## 结果分析 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# 连接维护(针对非阻塞IO) | ||
|
||
### 建立连接 | ||
|
||
* 建立连接的过程 | ||
连接的建立比较简单,server端通过socket(),bind(),listen(),并使用epoll ET模式监听listenfd的读请求,当TCP连接完成3次握手后,会触发listenfd的读事件,应用程序调用accept(),会检查已完成的连接队列,如果队列里有连接,就返回这个连接,出错或连接为空时返回-1。此时,已经可以进行正常的读写操作了。 当然,因为是ET模式,accept()要一直循环到就绪连接为空。 | ||
* 分析 | ||
之所以说建立连接的过程比较简单,是因为数据的通信已经由操作系统帮我们完成了,这里的通信是指3次握手的过程,这个过程不需要应用程序参与,当应用程序感知到连接时,此时该连接已经完成了3次握手的过程,accept就好了。另一个原因是一般情况下,连接的建立都是client发起的,server端被动建立连接就好了,也不会出现同时建立的情况。 | ||
* 限制 | ||
假设server只监听一个端口,一个连接就是一个四元组(原ip,原port,对端ip, 对端port),那么理论上可以建立2^48个连接,可是,fd可没有这么多(操作系统限制、用户进程限制)。当连接满了,如果空等而不连接,那么就绪队列也满了后,会导致新连接无法建立。这里的做法我参考了muduo,准备一个空的文件描述符,accept()后直接close(),这样对端不会收到RST,至少可以知道服务器正在运行。 | ||
|
||
### 关闭连接 | ||
|
||
相对于连接的建立,关闭连接则复杂的多,远不是一个close()那么简单,关闭连接要优雅。 | ||
|
||
##### 什么时候关闭连接? | ||
通常server和client都可以主动发Fin来关闭连接 | ||
|
||
* 对于client(非Keep-Alive),发送完请求后就可以shutdown()写端,然后收到server发来的应答,最后close掉连接。也可以不shutdown()写,等读完直接close。对于Keep-Alive的情况,就要看client的心情了,收到消息后可以断,也可以不断,server应该保证不主动断开。 | ||
|
||
* 对于server端,毫无疑问应该谨慎处理以上所有情况。具体说来: | ||
> * 出现各种关于连接的错误时,可以直接close()掉 | ||
> * 短连接超时的请求,可以直接close() | ||
> * 长连接对方长时间没有请求(如果没有保活机制),可以close() | ||
> * client发出Fin,server应当把消息发完,然后才可以close() | ||
> * 短连接正常结束,server可以close,也可以不close,大多数的实现是不close的(对HTTP1.1而言) | ||
|
||
##### EPOLLIN触发但是read()返回0的情况 | ||
|
||
这种情况通常有两个原因: | ||
> * 对端已经关闭了连接,这时再写该fd会出错,此时应该关闭连接 | ||
> * 对端只是shutdown()了写端,告诉server我已经写完了,但是还可以接收信息。server应该在写完所有的信息后再关闭连接。更优雅的做法是透明的传递这个行为,即server顺着关闭读端,然后发完数据后关闭。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# 项目目的 | ||
--- | ||
### 最初的想法 | ||
本项目是我在三星电子(中国)研发中心实习期间利用晚上和周末的时间完成的,实习期间我负责4K分辨率双鱼眼摄像头视频拼接的算法设计与实现,我希望能把其中的图像拼接部分的成果通过Web的方式展示出来,但因为涉及保密协议,不得不放弃这一想法。 | ||
|
||
### Web服务器能够很好的贯穿所学的知识 | ||
但是,Web服务器能够很好的贯穿之前所学的知识,之前看过的《C++ Primer》、《Effevtive C++》、《STL源码剖析》、《深度探索C++对象模型》、《TCP\IP详解卷1》、APUE、UNP,还包括了《后台开发核心技术与应用实践》等书,涵盖了 | ||
|
||
* TCP、HTTP协议 | ||
* 多进程多线程 | ||
* IO | ||
* 锁 | ||
* 通信 | ||
* C++语法 | ||
* 编程规范 | ||
* Linux环境下各种工具的使用 | ||
* 版本控制Git | ||
* Makefile和CMakeLists文件的编写 | ||
* 自动化构建工具Travis CI的使用 | ||
|
||
最终的版本在很多方面学习了muduo网络库,在看完陈硕的《Linux多线程服务端编程》后,对照着书把muduo的源码读了几遍,并重构了自己的服务器,最终的很多想法借鉴了muduo的思想。 |