如何写一个Web服务器

// 原文发表在 http://lifeofzjs.com/blog/2015/05/16/how-to-write-a-server/,之后项目的改进说明和更新都将在原文进行。

最近两个月的业余时间在写一个私人项目,目的是在Linux下写一个高性能Web服务器,名字叫Zaver。主体框架和基本功能已完成,还有一些高级功能日后会逐渐增加,代码放在了github。Zaver的框架会在代码量尽量少的情况下接近工业水平,而不像一些教科书上的toy server为了教原理而舍弃了很多原本server应该有的东西。在本篇文章中,我将一步步地阐明Zaver的设计方案和开发过程中遇到的困难以及相应的解决方法。

为什么要重复造轮子

几乎每个人每天都要或多或少和Web服务器打交道,比较著名的Web Server有Apache Httpd、Nginx、IIS。这些软件跑在成千上万台机器上为我们提供稳定的服务,当你打开浏览器输入网址,Web服务器就会把信息传给浏览器然后呈现在用户面前。那既然有那么多现成的、成熟稳定的web服务器,为什么还要重新造轮子,我认为理由有如下几点:

  • 夯实基础。一个优秀的开发者必须有扎实的基础,造轮子是一个很好的途径。学编译器?边看教材变写一个。学操作系统?写一个原型出来。编程这个领域只有自己动手实现了才敢说真正会了。现在正在学网络编程,所以就打算写一个Server。

  • 实现新功能。成熟的软件可能为了适应大众的需求导致不会太考虑你一个人的特殊需求,于是只能自己动手实现这个特殊需求。关于这一点Nginx做得相当得好了,它提供了让用户自定义的模块来定制自己需要的功能。

  • 帮助初学者容易地掌握成熟软件的架构。比如Nginx,虽然代码写得很漂亮,但是想完全看懂它的架构,以及它自定义的一些数据结构,得查相当多的资料和参考书籍,而这些架构和数据结构是为了提高软件的可伸缩性和效率所设计的,无关高并发server的本质部分,初学者会迷糊。而Zaver用最少的代码展示了一个高并发server应有的样子,虽然没有Nginx性能高,得到的好处是没有Nginx那么复杂,server架构完全展露在用户面前。

教科书上的server

学网络编程,第一个例子可能会是Tcp echo服务器。大概思路是server会listen在某个端口,调用accept等待客户的connect,等客户连接上时会返回一个fd(file descriptor),从fd里read,之后write同样的数据到这个fd,然后重新accept,在网上找到一个非常好的代码实现,链接点这里。如果你还不太懂这个程序,可以把它下载到本地编译运行一下,用telnet测试,你会发现在telnet里输入什么,马上就会显示什么。如果你之前还没有接触过网络编程,可能会突然领悟到,这和浏览器访问某个网址然后信息显示在屏幕上,整个原理是一模一样的!

学会了这个echo服务器是如何工作的以后,在此基础上拓展成一个web server非常简单,因为HTTP是建立在TCP之上的,无非多一些协议的解析。client在建立TCP连接之后发的是HTTP协议头和(可选的)数据,server接受到数据后先解析HTTP协议头,根据协议头里的信息发回相应的数据,浏览器把信息展现给用户,一次请求就完成了。

这个方法是一些书籍教网络编程的标准例程,比如《深入理解计算机系统》(CSAPP)在讲网络编程的时候就用这个思路实现了一个最简单的server,代码实现在这里,非常短,值得一读,特别是这个server即实现了静态内容又实现了动态内容,虽然效率不高,但已达到教学的目的。之后这本书用事件驱动优化了这个server,关于事件驱动会在后面讲。

虽然这个程序能正常工作,但它完全不能投

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值