`
mmdev
  • 浏览: 12927786 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

深入学习Tomcat----自己动手写服务器(附服务器源码)

 
阅读更多

相信大多Web开发者对Tomcat是非常熟悉的,众所周知Tomcat是一款非常好用的开源Servlet容器,您一定对这个最流行的Servlet容器充满好奇,虽然它并不像一个黑盒子那样让人无法触摸但是Tomcat的源码的确让人看起来头疼。笔者就在这里和大家共同分析一个简单的Web服务器是如何工作的源码下载地址

Web服务器

Web服务器是一个复杂的系统,一个Web服务器要为一个Servlet的请求提供服务,需要做三件事:

1、创建一个request对象并填充那些有可能被所引用的Servlet使用的信息,如参数、头部、cookies、查询字符串等等。一个request对象是javax.servlet.ServletRequest或javax.servlet.http.ServletRequest接口的一个实例

2、创建一个response对象,所引用的servlet使用它来给客户端发送响应。一个response对象是javax.servlet.ServletRequest或javax.servlet.http.ServletRequest接口的一个实例。

3、调用servlet的service方法,并传入request和response对象。这里servlet会从request对象取值,给response写值。

在正式展示代码之前还需要了解一些必须额HTTP的知识(如果您对此非常熟悉您可以直接看下面分析代码)

HTTP

HTTP的定义不知道的童鞋可以自己去度娘,这里主要要说的就是HTTP协议的格式

HTTP请求包括三部分

1、方法、统一资源标识符(URI)、协议/版本

2、请求的头部

3、主题内容

下面是一个HTTP请求的例子

  1. POST/examples/default.jspHTTP/1.1
  2. Accept:text/plain;text/html
  3. Accept-Language:en-gb
  4. Connection:Keep-Alive
  5. Host:localhost
  6. User-Agent:Mozilla/4.0(compatible;MSIE4.01;Windows98)
  7. Content-Length:33
  8. Content-Type:application/x-www-form-urlencoded
  9. Accept-Encoding:gzip,deflate
  10. lastName=Franks&firstName=Michael

第一行表明这是POST请求方法,/examples/default.jsp是URI,HTTP/1.1是协议以及版本。其中URI指明了一个互联网资源,这里通常是相对服务器根目录解释的,也就是说这个HTTP请求就是告诉服务器我需要这个文件目录如下:根目录/ examples/default.jsp。

最后一行是HTTP的主题内容,Servlet会处理请求的主题内容,然后返回给客户端HTTP响应。

类似于HTTP请求,一个HTTP响应也包括上面三个部分。

1、方法、统一资源标识符(URI)、协议/版本

2、响应的头部

3、主题内容

下面是一个HTTP响应的例子

  1. HTTP/1.1200OK
  2. Server:Microsoft-IIS/4.0
  3. Date:Mon,5Jan200413:13:33GMT
  4. Content-Type:text/html
  5. Last-Modified:Mon,5Jan200413:13:12GMT
  6. Content-Length:112
  7. <html>
  8. <head>
  9. <title>HTTPResponseExample</title>
  10. </head>
  11. <body>
  12. WelcometoBrainySoftware
  13. </body>
  14. </html>

第一行告诉协议版本,以及请求成功(200表示成功)

响应头部和请求头部一样,一些有用的信息。响应的主体就是响应本身HTML内容。

好了基本知识介绍完毕,下面开始解释代码

部分相关代码

  1. importjava.net.Socket;
  2. importjava.net.ServerSocket;
  3. importjava.net.InetAddress;
  4. importjava.io.InputStream;
  5. importjava.io.OutputStream;
  6. importjava.io.IOException;
  7. importjava.io.File;
  8. publicclassHttpServer{
  9. publicstaticfinalStringWEB_ROOT=System.getProperty("user.dir")
  10. +File.separator+"webroot";
  11. privatestaticfinalStringSHUTDOWN_COMMAND="/SHUTDOWN";
  12. privatebooleanshutdown=false;
  13. publicstaticvoidmain(String[]args){
  14. HttpServerserver=newHttpServer();
  15. server.await();
  16. }
  17. publicvoidawait(){
  18. ServerSocketserverSocket=null;
  19. intport=8080;
  20. try{
  21. serverSocket=newServerSocket(port,1,
  22. InetAddress.getByName("127.0.0.1"));
  23. }catch(IOExceptione){
  24. e.printStackTrace();
  25. System.exit(1);
  26. }
  27. while(!shutdown){
  28. Socketsocket=null;
  29. InputStreaminput=null;
  30. OutputStreamoutput=null;
  31. try{
  32. socket=serverSocket.accept();
  33. input=socket.getInputStream();
  34. output=socket.getOutputStream();
  35. Requestrequest=newRequest(input);
  36. request.parse();
  37. Responseresponse=newResponse(output);
  38. response.setRequest(request);
  39. response.sendStaticResource();
  40. socket.close();
  41. shutdown=request.getUri().equals(SHUTDOWN_COMMAND);
  42. }catch(Exceptione){
  43. e.printStackTrace();
  44. continue;
  45. }
  46. }
  47. }
  48. }

HttpServer类代表一个web服务器。首先提供一个WEB_ROOT所在的目录和它下面所有的子目录下静态资源。其次定义了一个中止服务的命令,也就是说当得到的请求后面跟/shutdown的时候停止服务,默认是把服务设置为开启。下面就是进入main函数了,首先实例化一个HttpServer类,然后就是通过await方法等待客户端发来的请求。如果客户端输入的URL不是http://localhost:8080/SHUTDOWN则表示不停止服务器,然后就是继续执行await方法中的内容,在await方法中最重要的就是定义两个对象,一个是request一个是response,下面就来说说Request和Response类。

  1. importjava.io.InputStream;
  2. importjava.io.IOException;
  3. publicclassRequest{
  4. privateInputStreaminput;
  5. privateStringuri;
  6. publicRequest(InputStreaminput){
  7. this.input=input;
  8. }
  9. publicvoidparse(){
  10. StringBufferrequest=newStringBuffer(2048);
  11. inti;
  12. byte[]buffer=newbyte[2048];
  13. try{
  14. i=input.read(buffer);
  15. }catch(IOExceptione){
  16. e.printStackTrace();
  17. i=-1;
  18. }
  19. for(intj=0;j<i;j++){
  20. request.append((char)buffer[j]);
  21. }
  22. System.out.print(request.toString());
  23. uri=parseUri(request.toString());
  24. }
  25. privateStringparseUri(StringrequestString){
  26. intindex1,index2;
  27. index1=requestString.indexOf('');
  28. if(index1!=-1){
  29. index2=requestString.indexOf('',index1+1);
  30. if(index2>index1)
  31. returnrequestString.substring(index1+1,index2);
  32. }
  33. returnnull;
  34. }
  35. publicStringgetUri(){
  36. returnuri;
  37. }
  38. }

首先调用InputStream对象中的read方法获取HTTP请求的原始数据,然后在parseUri方法中获得uri也就是要请求的静态资源。说白了Request类的主要作用就是告诉服务器用户要的是什么也就是在http://localhost:8080后面出现的东西。

  1. importjava.io.OutputStream;
  2. importjava.io.IOException;
  3. importjava.io.FileInputStream;
  4. importjava.io.File;
  5. publicclassResponse{
  6. privatestaticfinalintBUFFER_SIZE=1024;
  7. Requestrequest;
  8. OutputStreamoutput;
  9. publicResponse(OutputStreamoutput){
  10. this.output=output;
  11. }
  12. publicvoidsetRequest(Requestrequest){
  13. this.request=request;
  14. }
  15. publicvoidsendStaticResource()throwsIOException{
  16. byte[]bytes=newbyte[BUFFER_SIZE];
  17. FileInputStreamfis=null;
  18. try{
  19. Filefile=newFile(HttpServer.WEB_ROOT,request.getUri());
  20. if(file.exists()){
  21. fis=newFileInputStream(file);
  22. intch=fis.read(bytes,0,BUFFER_SIZE);
  23. while(ch!=-1){
  24. output.write(bytes,0,ch);
  25. ch=fis.read(bytes,0,BUFFER_SIZE);
  26. }
  27. }else{
  28. StringerrorMessage="HTTP/1.1404FileNotFound\r\n"
  29. +"Content-Type:text/html\r\n"
  30. +"Content-Length:23\r\n"+"\r\n"
  31. +"<h1>FileNotFound</h1>";
  32. output.write(errorMessage.getBytes());
  33. }
  34. }catch(Exceptione){
  35. System.out.println(e.toString());
  36. }finally{
  37. if(fis!=null)
  38. fis.close();
  39. }
  40. }
  41. }

Response类代表一个HTTP响应。首先Response接收一个OutputStream对象,然后通过sendStaticResource方法对接收的Request进行处理,整个处理过程就是根据请求在服务器端进行寻找对应静态资源的过程。找到所需要的资源后发送给客户端然后让客户端显示出来。

运行程序

运行上面的HttpServer类,然后在浏览器的地址栏中键入下面的地址:http:localhost:8080/index.jsp,然后你会在浏览器中看到index.jsp页面。

在控制台可以看到类似于下面的HTTP请求

  1. GET/index.jspHTTP/1.1
  2. Host:localhost:8080
  3. Connection:keep-alive
  4. Cache-Control:max-age=0
  5. User-Agent:Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/535.7(KHTML,likeGecko)Chrome/16.0.912.75Safari/535.7360EE
  6. Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  7. Accept-Encoding:gzip,deflate,sdch
  8. Accept-Language:zh-CN,zh;q=0.8
  9. Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3


小结

上面自己动手写的这个所谓的服务器仅仅有三个类组成,从功能上来说他只能显示一些静态的资源,并不是全部功能。一个优秀的服务器还有很多细节要做,但是出于学习的目的大家现在有这些了解就足够了,后面还会有对服务器的详细介绍,敬请期待。

分享到:
评论

相关推荐

    Tomcat服务器开发源码

    自己开发的Tomcat服务器,需要深入理解Tomcat源码的同学可以下载它学习之,开发出来的Tomcat支持JSP、Servlet

    tomcat学习源码

    资源是关于tomcat深入剖析的源码. 本书深入剖析Tomcat 4和Tomcat 5中的每个组件,并揭示其内部工作原理。通过学习本书,你将可以自行开发Tomcat组件,或者扩展已有的组件。 Tomcat是目前比较流行的Web服务器之一。...

    Tomcat与Java Web开发技术详解 (14-26章源码)孙卫琴

    本书语言深入浅出、通俗易懂,无论对于Java Web开发的新手还是行家来说,本书都是精通Tomcat和开发Java Web应用的必备的实用手册。本书还可作为高校相关专业学生学习Java Web开发的参考书,以及企业Java Web培训教材...

    JSP设计第二版 - 内附源码(PDF中文版)

    书中还展示了如何用Apache Tomcat服务器启动JSP,并详细讲述了JSP语法和功能、错误处理和调试、身份验证和个性化,以及如何将JSTL用于数据库访问、XML处理及国际化等。 本书可以满足两类想学习JSP的专业人士的不同...

    Struts2教程配套源码

    Web服务器:Tomcat6 Struts版本:struts2.1.6.jar JDK版本:JDK1.6.0_33-b03 J2EE版本:Java EE5.0 虽然MyEclipse8.5支持Struts2,但是为了深入了解struts2,所以我们到struts.apache.org去下载Struts2安装包。...

    JSP设计第二版(附源码)

    JSP设计第二版(附源码) 《JSP设计(第二版)》得到了彻底的修订和更新,包括了JSP规范1.2版本中的重大变化。它包括关于JSP Standard Tag Library(JSTL)的详细内容 —— JSTL是一组殷切加入的JSP元素规范,用于多数...

    Javaweb项目,使用Tomcat本地服务器,使用servlet以及HTML、CSS、JavaScript、AJAX的校园外卖

    Javaweb项目,编译器为IDEA,使用Tomcat本地服务器,使用servlet以及HTML、CSS、JavaScript、AJAX的校园外卖系统,采用算法协同过滤与倒排索引等.zip 适合学习/练手、毕业设计、课程设计、期末/期中/大作业、工程实...

    高效便捷的信息化票务处理系统。 本系统依托SSM框架的应用,采用Tomcat作后台服务器

    本系统依托SSM框架的应用,采用Tomcat作后台服务器….zip 适合学习/练手、毕业设计、课程设计、期末/期中/大作业、工程实训、相关项目/竞赛学习等。 项目具有较高的学习借鉴价值,也可直接拿来修改复现。可以在这些...

    基于SSM的面向学生成绩分析系统(源码+部署说明+演示视频+源码介绍).zip

    包括环境配置、数据库连接配置、Tomcat服务器配置等。通过阅读部署说明,开发者可以轻松地在自己的计算机上搭建起一个运行该项目的环境。演示视频部分提供了一个实际操作的演示视频,展示了如何在浏览器中访问系统...

    JSP设计第二版(附源码).rar

    书中还展示了如何用Apache Tomcat服务器启动JSP,并详细讲述了JSP语法和功能、错误处理和调试、身份验证和个性化,以及如何将JSTL用于数据库访问、XML处理及国际化等。 《JSP设计(第二版)》可以满足两类想学习JSP的...

    基于协同过滤算法的在线教育平台源码(前后端分离)+项目使用说明.zip

    | Web服务器 | Tomcat 9.0.41 | | 数据库版本 | MySQL 8.0.22 | | 本地操作系统 | Windows 10 | | 服务器操作系统 | Linux CentOS | 后端系统文件架构 ``` zutmooc // 后端根项目 ├── common // 通用代码层 │ ...

    最新SpringBoot项目书籍学习平台.zip

    综上所述,这个基于Spring Boot的书籍学习平台以其丰富的功能、良好的用户体验和强大的可扩展性,对于想要深入学习Spring Boot和全栈开发的开发者来说是一个很好的实践项目。它同样适合作为学生的毕业设计或者课程...

    基于Java的疫情信息登记数据库系统的设计与实现【附源码】

    系统平台:采用B/S体系结构,Microsoft Windows 10为服务端操作系统,Tomcat8.0为Web服务器,客户端采用 Windows 10操作系统,Internet Explorer浏览器,数据库采用MySQL5.5。 开发工具:采用Java语言,JSP技术。 ...

    逆向工程源码

    虽然活儿干完了,项目也跑了起来,但是对于里面的技术点自己还是得深入到代码中去研究,去感受,还有其中业务逻辑的梳理,以及设计思想的升华都需要去了解去学习。 只要相信自己,并付出与行动,终究会取得胜利的...

    最新springboot学生综合成绩测评系统.zip

    - 使用Tomcat作为Web服务器,支持B/S(Browser/Server,浏览器/服务器)模式的系统架构。 2. **功能模块**: - 系统涉及多个核心功能,如学生管理、试题信息管理、测评试题管理等,旨在满足日常学生综合测评的需求。...

    最全的Java程序员知识(专业知识+面试+视频教程)学习资料合集.zip

    最全的Java程序员知识学习资料合集,共20+专题。 开源框架面试题系列:Spring+SpringMVC+MyBatis 分布式限流面试专题系列:Nginx+zookeeper 分布式通讯面试专题系列:ActiveMQ+RabbitMQ+Kafka 分布式数据库面试专题...

    基于JavaWeb的高校科研成果管理系统设计与实现

    能学到什么:①MVC 设计模式、Docker 技术、MySQL 数据库技术、Tomcat 服务器技术是怎么在系统中体现的;②系统安全模块、数据查询统计模块、科研信息管理模块、人员信息管理模块、通用信息管理模块都是如何设计和...

    本人学习EXT以来的宝贵财富,1年多的积累啊!!!

    然后部署到tomcat等服务器上,就可以观看example下面的所有例子。 有Ext官方自带的,&lt;深入浅出ExtJS&gt;一书的所有源码,73个Ext官方论坛收集的用户扩展控件。几个自己写的例子。 有任何问题可以找我 QQ:370735745 ...

    建筑材料租赁系统,后端框架SSM,前端框架LayUI,数据库MySQL

    建筑材料租赁系统,后端框架SSM,前端框架LayUI,数据库MySQL,开发工具IDEA,Web服务器Tomcat,毕业设计。功能:客户管理,材料管理,订单管理,修改密码.zip 适合学习/练手、毕业设计、课程设计、期末/期中/大作业...

    类似于微信公众号系统的网页版公众号系统

    基于JSP+HTML+JQuery实现,服务器为Tomcat 7, 未重构.zip 适合学习/练手、毕业设计、课程设计、期末/期中/大作业、工程实训、相关项目/竞赛学习等。 项目具有较高的学习借鉴价值,也可直接拿来修改复现。可以在这些...

Global site tag (gtag.js) - Google Analytics