基于epoll+threadpool的webServer分析与实现

该webServer使用epoll+threadpool实现,支持GET、POST方法,并添加CGI进行数据计算并返回网页信息,可以解析返回html、picture、mp3、js、css等文件,可以实现稳定的运行。 使用c++编写。

源码请看我的Github。

流程简述

  • 启动服务器,在浏览器输入服务器地址,将向服务器发送HTTP请求

  • 服务器接收数据,新建任务,将任务添加到任务队列

  • 从线程池中唤醒某线程,执行任务。若没有任务线程会处于wait状态;若任务过多,会存储在任务队列中,等待空闲线程来执行

  • 某线程获得任务后,读取浏览器发送的请求信息,进行解析HTTP首部,根据对应的结果来进行相应的处理,返回信息,若文件不存在则返回404.html,若请求方法不存在则返回501错误信息。

  • 若是POST,则需要调用CGI进行处理,并返回相应的信息。

  • 任务结束后,需要进行delete,因为在主进程中,为避免任务未运行完便被析构,需要使用new来新建对象,为避免内存泄露,需要在任务结束后使用delete释放资源。虽然这样使得newdelete分离,但是可以保证程序的正常运行。

  • 线程池结束后,需要唤醒阻塞中的所有线程,以使其正常退出。

具体实现细节

  • 由于在实现线程池时,需要用到任务队列,为保证任务队列在添加、删除元素时不会出错,需要对其加锁;同样由于在线程池中线程的运行与否需要受到控制,因此需要使用条件变量来使线程保持同步。所以在locker.h中定义了两个类:互斥锁、条件变量。互斥锁比较简单,所以说一下条件变量需要注意的细节:

    • 条件变量需要与互斥锁配合使用。由于条件变量的操作并非原子操作,因此在进行相关变量状态转变的时候,多线程若操作统一条件变量会造成错误。因此在条件变量之前需要加互斥锁进行保护,结束后及时解锁。
  • 由于每次接收到数据时,需要新建一个任务,因此在task.h中定义一个封装任务信息的类。该类负责接受来自浏览器具体的请求信息,再进行解析,根据对应的结果进行处理与返回网页信息等。

    • 由于在任务结束后会调用delete,从而会进行析构,因此可以在Task的析构函数中关闭连接。即每个任务(每个HTTP请求)对应一个线程,每次任务结束后都会关闭与浏览器连接。
    • 在每次任务执行时,为避免读取数据出错,需要循环读取,直到对方关闭连接(recv返回值=0)或请求处理完成后退出循环,即一次任务完成后也要退出循环。PS:一定要注意关闭连接的时间,否则浏览器会一直处于pending状态
  • threadPool.h存放线程池的定义与实现。线程池提供线程的调度,及时处理任务队列中的任务;若任务队列为空,则所有线程处于阻塞状态。由于使用模板类,因此需要将类定义与方法实现放在一个文件夹下,因为模板类的成员函数不能单独编译。详见我的另一篇博客:线程池的分析与实现。

  • webServer.hwebServer.cpp存放WebServer类的定义与实现。该类主要进行socket的创建,绑定,监听,与accept,使用epoll实现。在接收到新连接时,将fd注册到内核事件表;有数据写入时,便使用new新建任务,并添加到线程池。由于任务使用new创建,因此任务结束后需要及时delete task。

使用介绍

  • 由于在上传时,将mp3文件删除(上传缓慢),因此需要在与index.html同级的目录下放一个mp3文件,并命名为1.mp3

  • 打开终端,在makefile目录下,输入./server port以运行服务器,其中port为端口号,以下以8080端口为例:
    终端输入 :

./server 8080

打开浏览器,在网址输入:

localhost:8080

或输入网址:

127.0.0.1:8080

即可连接服务器。

  • 如果要使用自己的网页,只要将网页放到与webServer.cpp统一目录下,把index.html用新的主页覆盖即可。

参考:《Linux高性能服务器编程》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/381874.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flex2.0实现文件上传功能(服务器为ASP.NET)

简介:新的Flex2.0类库里提供了文件类,方便了上传/下载文件。下面的程序demo演示了Flex2.0生成flash来访问本地文件,在flash里上传用户选择的文件到服务器,flash客户端可以处理文件上传进度等多个事件,服务器端是C#写的…

UVA 116——Unidirectional TSP

题意:给定一个n*m的矩阵,从第一列任意位置向右,右下,右上走一格,可以循环,要求经过的数字的和最小。 思路:记忆化搜索。每次有三个状态,从这三个状态中选择出最优的一个,…

【高性能定时器】 时间轮

时间轮 简述 顾名思义,时间轮就像一个轮子,在转动的时候外界会指向轮子不同的区域,该区域就可以被使用。因此只要将不同时间的定时器按照一定的方法散列到时间轮的不同槽(即时间轮划分的区域)之中,就可以实…

知识管理的三种策略

知识管理的三种策略 面向流程的知识管理战略-实施篇(上)(AMT研究院 周瑛 编译) 转载于:https://www.cnblogs.com/yangfada/archive/2006/01/24/322381.html

java 考试复习整理——JAVA类和类成员的修饰符

今天整理了一下以前学的JAVA的类和类成员的修饰符,考试的时候可能会考到。一:访问修饰符:1.省略访问修饰符:具有默认的访问特性,即具有包访问特性,只能被同一个包中的类使用。2.public访问修饰符&#xff1…

【安利】程序猿作图神器 - Graphviz

还在为在linux下画二叉树等图苦恼吗,现在就安利一波linux程序猿的作图神器——Graphviz。(本来在写其他东西,刚好要绘图,强行插入一篇blog) Graphviz (Graph Visualization Software) 是一个由AT&T实验室启动的开源…

仿ISQL功能的实现,可以实现批处理功能

具体请见下载文件:/Files/bigmouthz/DNet写的数据库isql执行程序(含源码).rar部分代码如下: DBCore.DataBaseVisitor.AbsDBHelper dbhelper null ; private void bt_DBLink_Click(object sender, System.EventArgs e) { try …

uva 11400——Lighting System Design

题意: 给定一些灯泡,每种灯泡有不同的电压v,电源费用k,每个灯泡的费用c,所需的灯泡的数量L,同种灯泡可以使用相同电源,问最小花费。 思路:dp,每种灯泡要么选要么不选两种…

【高性能定时器】时间堆(最小堆)

最小堆及其应用:时间堆 最小堆及其应用:时间堆 一、 堆1. 概念2. 最小堆的实现3. 性质4. 代码 二、时间堆1. 概念简述2. 实现细节3. 代码 一、 堆 1. 概念 堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或…

uva 11584——Partitioning by Palindromes

题意&#xff1a;给定一个字符串&#xff0c;把该字符串划分为最少的回文串。 思路&#xff1a;dp&#xff0c;到达i点的回文串长度都存起来&#xff0c;那么dp[i]min(以i为结尾的最短的回文串长度&#xff09;。 code&#xff1a; #include <bits/stdc.h> using namespa…

【操作系统】生产者消费者问题

生产者消费者模型 文章目录生产者消费者模型 [toc]一、 生产者消费者问题二、 问题分析三、 伪代码实现四、代码实现&#xff08;C&#xff09;五、 互斥锁与条件变量的使用比较一、 生产者消费者问题 生产者消费者问题&#xff08;英语&#xff1a;Producer-consumer problem&…

2006年2月8日 再见,Borland

昨天早上从David I的Blog上看到了Borland出售IDE产品线转而全面发展ALM的消息,既感到惋惜又似乎感到新的希望 之所以惋惜是因为Delphi是我第一个喜欢的语言&#xff0c;也是Delphi第一次让我对编程产生兴趣&#xff0c;还记得我的第一个小软件就是Delphi5.0做的&#xff0c;而如…

【计算机网络】三次握手与四次挥手

三次握手与四次挥手 通过TCP/IP协议的学习&#xff0c;我们可以知道TCP协议是一种面向连接的、可靠的传输协议。其中&#xff0c;为了保证客户端与服务器连接的有效性&#xff0c;就有了本篇文章所要介绍的“三次挥手”&#xff1b;而“四次挥手”则是为了保证连接的正确断开。…

uva 10003——Cutting Sticks

题意&#xff1a;给定一长为L的木棍和n个切割点&#xff0c;每次切割的费用为切割的长度&#xff0c;求最小的费用。 思路&#xff1a;dp,子问题是区间&#xff08;i&#xff0c;j&#xff09;的最小费用&#xff0c;临界是&#xff08;i,j)只有一个切割点。dp[i,j]min(dp[i,k]…

小叔叔又飞走了

小叔叔在飞走之前&#xff0c;昨天晚上&#xff0c;给我们看了&#xff0c;他回老家拍下的&#xff0c;家里每个人的视频&#xff0c;&#xff08;前面这半句话说得好累&#xff0c;不过应该不是病句&#xff09;让我们看了动情又亲切&#xff0c;至少我是这么觉得。一个大家庭…

系统调用中断(EINTR)与SIGCHLD信号的处理

一、被中断的系统调用(EINTR)的理解1. 慢系统调用是&#xff1f;2. 慢系统调用的类别3. EINTR产生的原因5. 一般处理方法 二、SIGCHLD信号的处理1. SIGCHLD信号的产生2. SIGCHLD信号的处理3. 不处理SIGCHLD的后果 三、示例代码 一、被中断的系统调用(EINTR)的理解 1. 慢系…

SMO写的查看数据库信息的代码

要分析一个比较大的数据库&#xff0c;里面的表太多了&#xff0c;虽然是中文命名&#xff0c;但在2005的Management Studio中查看还是比较麻烦&#xff0c;比如&#xff0c;我想查看具有相同字段名称的表的情况就不好办。于是用SMO写了这个东东。代码比较乱&#xff0c;没有进…

uva 1626——Brackets sequence

题意&#xff1a;定义满足 1.空序列 2.&#xff08;&#xff09;&#xff08;X&#xff09;及括号和其括起来的合法序列 3.【】要求和&#xff08;&#xff09;相同 都是合法的串。 然后给定一段序列&#xff0c;求添加最小的&#xff08;&#xff09;或【】使得序列合法。…

定时器与超时的设置

一、相关时间函数1. gettimeofday()2. time()3. clock() 二、间隔定时器1. setitimerval()2. getitimerval()3. 实时定时器的使用 三、为阻塞操作设置超时1. alarm()2. 给read()设置读超时 一、相关时间函数 1. gettimeofday() 获取日历时间。 #include <sys/time.…

世界 Web 2.0 网站评奖揭晓

Web 2.0真的成了我们在互联网不可或缺的一部分&#xff0c;成了互联网的未来趋势.(你现在用了吗?)国外的 SEOmoz 网站最近举行了一个 Over 300 web 2.0 sites reviewed and ranked 活动列出了300多家 Web 2.0 网站, 分为38个分类, 评出了每个类别下的前三名, 并采访了 20位获奖…