也谈如何写一个Webserver(-)
关于如何写一个Webserver,很多大咖都发表过类似的文章.趁着这个五一假期,我也来凑个份子.
我写Webserver的原因,还得从如何将http协议传送的消息解析说起.当时,我只是想了解一下http的消息解析过程,好能够提高基于http协议的消息处理效率,所以就在网上搜了一下,发现很多人都在用nodejs的http-parser,也许是智商上限封顶^_^!,我居然没太看懂大神的代码逻辑.后来也考察过h2o这个项目的parser,无奈还是没有能领悟大神的精神^_^!.
怎么办...,挣扎了半天,最终决定硬着头皮自己写一个http消息的parser吧.就酱,就有了后来我写Maestro Webserver的故事.
既然谈到了http message的解析,那今天这第一篇随笔就谈这个东西吧.http协议的内容说起来历史太久远了,我不是历史老师,网上很多讲解都很棒,我就不多说了.此外,RFC2616, RFC7231等文档也明确的讲解了协议的含义.不过还是应该吐槽一下RFC文档的晦涩难懂哈...
还是让我引用一段相对清晰的关于http message的RFC讲解吧
HTTP messages consist of requests from client to server and responses
from server to client. HTTP-message = Request | Response ; HTTP/1.1 messages Request (section 5) and Response (section 6) messages use the generic
message format of RFC 822 [9] for transferring entities (the payload
of the message). Both types of message consist of a start-line, zero
or more header fields (also known as "headers"), an empty line (i.e.,
a line with nothing preceding the CRLF) indicating the end of the
header fields, and possibly a message-body. generic-message = start-line
*(message-header CRLF)
CRLF
[ message-body ]
start-line = Request-Line | Status-Line
从这段文字中,我们可以知道不论是request还是response,http message分三段,即start-line,message headers和message body.
那么,在设计我的messge结构体时(对了,我是用C语言开发的),我会包含这三段内容.我并没有把parser写成独立的单一函数,而是将他们分解成了一组能重复被调用的更小的函数.而从封装的角度来说,我也没有遵守尽量封装数据结构体的原则.我的目的很简单,那就是,简单易懂,容易调用(这会不会被老师调打一顿:-).
还是看看定义的数据结构体吧.
typedef struct {
int method; /* GET/POST... */
char *path;
int ver_major;
int ver_minor;
int code; /* status code */
char *status; /* status text */
sllist_t *headers;
int len_startline;
int len_headers;
unsigned char *body;
unsigned char *body_zipped;
unsigned char *body_s; /* point to the range start of the body */
size_t len_body;
} httpmsg_t;
先不用看和body相关的部分,因为我会在后续如何写Webserver中介绍相关的内容(涉及到body的压缩,断点续传等等).
下面是相关的函数,
int msg_parse(sllist_t *headers,
unsigned char **startline,
unsigned char **body,
size_t *len_body,
const unsigned char *buf);
这个是对底层message进行解析的函数,再此之上,我用两个函数封装了它,分别用于解析http request和http response.
httpmsg_t *http_parse_req(const unsigned char *buf);
httpmsg_t *http_parse_rep(const unsigned char *buf);
我写这些底层函数的原则是,尽量利用上一步的结果,不做重复的计算,比如,同一字符串的长度不要多次通过strlen计算,希望这样应该能提高(微不足道^_^!)的性能吧.
在上面的httpmsg_t结构体中,我用了单链表来管理http headers,因为headers的数量不是很多,单链表轮询反而速度更快.
至于上述函数如何实现,感兴趣朋友可以请访问我的github项目,链接https://github.com/grassroot72/Maestro2.
欢迎和我探讨..
我会在第二篇内容里介绍socket和epoll在Webserver中的应用...
也谈如何写一个Webserver(-)的更多相关文章
- 也谈如何写一个Webserver(三)
在上一篇里,我介绍了如何应用socket和epoll来组织和管理从客户端(如,浏览器)传入的连接,通过设置非阻塞连接让Webserver有更好的性能. 下面,我介绍一下在我写的Webserver Ma ...
- 比最差的API(ETW)更差的API(LTTng)是如何炼成的, 谈如何写一个好的接口
最近这几天在帮柠檬看她的APM系统要如何收集.Net运行时的各种事件, 这些事件包括线程开始, JIT执行, GC触发等等. .Net在windows上(NetFramework, CoreCLR)通 ...
- 如何写一个简单的webserver(一):最简实现
本文主要讲述如何用C/C++在Linux环境下写一个简单的支持并发的web服务器,并不考虑服务器的健壮性.安全性.性能等一系列因素. 在本文中,该服务器仅支持GET请求. 项目地址:https://g ...
- 郑晔谈 Moco 框架的开发:写一个好的内部 DSL ,写一个表达性好的程序
作者:张龙 出处:http://www.infoq.com/cn/news/2013/07/zhengye-on-moco 郑晔谈Moco框架的开发:写一个好的内部DSL,写一个表达性好的程序 作者 ...
- 张小龙谈如何写E-mail软件
编者语:鼎鼎大名的Foxmail软件制作者,你一定不会陌生吧!本刊第三期特刊还刊登过此君的生活照一张,可谓威风八面.小编此次突发奇想,“死缠烂打”,费了九牛二虎之力,终于约他写了一篇有关写E-mail ...
- Android在如何建立一个WebServer
今天老板交待任务最终完成了,感觉收获颇多,所以写一个关于它的记录,首先,看一下.老板的需求 需求: 希望移动端的用户标识(IMEI)和HTML页面的用户标识(Cookie)连接起来,当中HTML页面可 ...
- 用c++写一个 “hello,world” 的 FastCGI程序
原文:http://chriswu.me/blog/writing-hello-world-in-fcgi-with-c-plus-plus/ 上面的连接地址给出的是作者的原文地址. 另外一个作者稍微 ...
- 动手写一个简单版的谷歌TPU-指令集
系列目录 谷歌TPU概述和简化 基本单元-矩阵乘法阵列 基本单元-归一化和池化(待发布) TPU中的指令集 SimpleTPU实例: (计划中) 拓展 TPU的边界(规划中) 重新审视深度神经网络中的 ...
- 来,我们手写一个简易版的mock.js吧(模拟fetch && Ajax请求)
预期的mock的使用方式 首先我们从使用的角度出发,思考编码过程 M1. 通过配置文件配置url和response M2. 自动检测环境为开发环境时启动Mock.js M3. mock代码能直接覆盖g ...
随机推荐
- openwrt编译加载龙尚U9300模组上网
硬件平台:MT7628A openwrt版本:MTK_SDK 1.添加模组信息 /build_dir/target-mipsel_24kc_musl/linux-ramips_mt76x8/linux ...
- 后端程序员之路 59、go uiprogress
gosuri/uiprogress: A go library to render progress bars in terminal applicationshttps://github.com/g ...
- 后端程序员之路 33、Index搜索引擎实现分析2-对外接口和大体流程
# index_manager的单例是index server对外的唯一接口,part_indexer是index搜索的核心部分,index_manager持有了一组part_indexer. typ ...
- Layui 源码浅读(模块加载原理)
经典开场 // Layui ;! function (win) { var Lay = function () { this.v = '2.5.5'; }; win.layui = new Lay() ...
- AOP(面向切面编程)大概了解一下
前言 上一篇在聊MemoryCache的时候,用到了Autofac提供的拦截器进行面向切面编程,很明显能体会到其优势,既然涉及到了,那就趁热打铁,一起来探探面向切面编程. 正文 1. 概述 在软件业, ...
- CloudQuery v1.3.4 版本更新
Hello,大家好久不见! 上一个版本(v1.3.3)发布已是春节前的事情了,此次 v1.3.4 是 CloudQuery 社区版在辛丑牛年的第一个版本发布.本次更新增加了新功能,优化了原有功能点.同 ...
- win8 下删除服务
1.右键 我的电脑-管理-服务和应用程序-服务,找到想要删除的服务,双击后复制服务名称. 2.管理员身份运行cmd 在命令框中输入 sc delete "secbizsrv" 就删 ...
- js前端技术
一.前端技术 1.HTML HTML(hypertext markup language)超文本标记语言,不同于编程语言. 超文本就是超出纯文本的范畴,描述文本的颜色.大小.字体. HTML由一个个标 ...
- C# 获取Word文本高亮和背景(附vb.net代码)
Word中的文本高亮和背景是通过不同方法来设置的.文本高亮(Text Highlight Color)是通过[字体]中的快速工具栏设置:文本背景(Text Background/Shading)是通过 ...
- Bonuses on a Line Gym - 102569B
题目链接:https://vjudge.net/problem/Gym-102569B 题意:数轴上有N个点,从0出发最多走t步问最多经过几个点. 思路:分开存负数点和整数点,然后枚举每个端点,某个点 ...