这篇文章主要写一下如何实现一个简单的http服务器,并且借由这个问题讨论一下别的相关问题。首先实现一个http服务器是一件很难的事吗?这个问题不好回答,如果是一个demo级的http服务器,答案是:很简单,可以说是JAVA刚入门水平就可以做到的。如果是一个可供实际生产的、性能优良,架构优雅的服务器,答案是:很不容易,对大部分的人来说可能很难。不过不管是demo还是成熟的生产用的http服务器,他们核心的部分应该都是相似的,下面我们来分析一下服务器的工作过程:
首先何谓“服务”?服务就是按照客户的要求来完成客户的需求。服务器更具体的表现形式是按照客户的的请求来执行某种操作,返回指定数据,这里的数据和请求更具体的表现形式通常是字符串。也就是说客户端发给服务器一个包含客户端需求的字符串,服务端通过解析客户端发来的字符串,获取客户端的需求,然后完成需求。那么问题来了,服务端如何解析客户端发来的字符串呢?他们之间可是素不相识的,每个客户端按何种组织方式来发送自己的需求对服务器来说完全是不可预期的。于是这就需要一个统一的规范来统一客户端的请求和服务端的返回,以及一些别的行为规范,于是http协议合情合理的出现了。现在事情就变成客户端发给服务器一个满足http协议的、包含客户端需求的字符串,服务端根据http协议来解析客户端发来的字符串获取客户端的需求,然后完成需求,返回符合http协议的字符串给客户端。再然后这里的“发送”,“返回”又具体是什么呢?它们就是客户端和服务器之间通过socket连接执行的一些IO操作。这样分析之后我们大概知道整个的工作流程:客户端建立一个连接到服务端,执行IO操作,把满足http协议的字符串发送给服务器,服务器根据http协议来解析客户端发来的字符串的含义,然后执行对应操作,最后把作为返回结果的、满足http协议的字符串执行IO操作发送给客户端。
通过上面简单的分析我们大概知道http服务器具体干了啥(实际比较复杂)以及我们需要哪些基础前置知识:
- http协议(编程语言无关,核心):参见RFC2616
- IO操作(编程语言有关):各大编程语言的IO模块
- 字符串操作:这就是各大公司考算法题的原因吧(望天==)
后续当然还有:
- 多线程并发优化处理
- 设计模式
- ......
下面是我用JAVA实现一个HTTP服务器,我这个服务器不是简单的小demo(demo只需两个JAVA 类即可搞定==),当然也不是可以生产用的(你可以把它写成可以生成用的),先导知识为Java NIO编程和Java 多线程编程,代码太长不贴,放在github。代码地址:Crab
项目截图:
项目的目的是什么呢?最重要的目的是希望可以写出规范化的、工程化的代码以及项目,特别是与入门者来说常常只写一些玩具式的demo,或者盲目的去看一下大型项目的源码,我觉得这样对自己水平的提升帮助有限,事实上我认为对一个人提升最大的是从最开始就接触某个项目或领域,从它萌芽的时候开始参与,一步步由项目和问题驱动着来学习,在遇到问题的时候可以想办法来解决它,想不出来可以去别的项目看看别人是如何解决的,这样既提高了自己的水平,也对别的项目有了更深的理解,知道别人为何这样做,而不是去记忆别人是怎么做的。这里引出的一个问题是:当我们在阅读源码时我认为至少要带着这样几个问题:1.这个东西是干什么的,解决了什么问题。2。这里作者这里为什么要这样做,他的目的是什么,他想干什么。3.我现在想要做的东西需要它吗?需要到什么程度(会用?会魔改?)?以项目驱动学习,把从书上,别人源码里的技巧立马用到自己的项目里,才可以让知识真的化为己用。
题外话:当我们学习时我们通常实际上在学习什么?
我的观点是我们在学习时通常实际上更多的在学习各种规范,比如JavaWeb其实通常就是Java语言规范+各种框架的使用规范+网络协议规范,因为计算机科学以及很多工程科学实际是一个人造的体系,支撑这个体系的就是各种规范,修补和发展这个体系也是依赖于各种规范,由于规范可以人造,因此规范可以说是学不完的,因为会不停的有新的规范出来,所以说学无止境。说起学无止境好像每门科学都是学无止境的,我认为科学大致可以分成两种,一直是研究的是基于一种人造的体系,一直是基于自然的体系(当然人造的最后也是基于自然的)。前者的学无止境是由于人类创造的无止境,不断地会有新的问题和规范被创造出来,后者的学无止境更多的是由于大自然的无止境,大到宇宙星辰,小到原子夸克,浩瀚无边地大自然的规范就在那里等待人们去发现。