`
aijuans
  • 浏览: 1566069 次
社区版块
存档分类
最新评论

试解析Tomcat运行原理(一)--- socket通讯

阅读更多

  关于这篇文章也确实筹划了很久,今天决定开篇写第一篇,说起tomcat首先很容易联想到IIS,因为我最开始使用的就是.net技术,我第一次使用asp写学生成绩管理系统后,很茫然如何让别人都能看到或者说使用这个系统呢?由此认识了IIS,它是一个web容器,天生的多线程,及时响应用户提交的请求返回html页面,这就是我了解的最初的web容器的功能,由此我们来认识tomcat也并不困难,可以的话,在了解完tomcat后我们可以继续了解jbossjetty等,好我们进入主题。

  我们在平时开发的过程中是在使用eclipse时候才启动tomcat,对于一个web容器而言,简而言之,它是系统的一个守护进程,守护着对这台服务器某个端口发起的请求,基于这一点,它就需要一个监听程序,这个监听程序来获取来自这个端口的特定请求的数据,ok,直接点讲,我们这里使用Socket来获取某个端口,通常是80端口的http请求,通过简单的Java

  程序的死循环(粗糙的做法,后面逐步优化)来实现不断的获取80端口http请求,来达到监听80端口http请求的目的。java.net包下面的SocketServerSocket两个类就能实现我们对8080端口的监听,去除中间的逻辑代码,我们只看这个两个类的演绎的话如下:

 

1 ServerSocket serverSocket = new ServerSocket(8080, 1, InetAddress.getByName("10.10.10.106"));

 

  对本机的8080端口进行监听

 

1 socket = serverSocket.accept();             
2 input = socket.getInputStream(); 
3 output = socket.getOutputStream(); 

 

  以上代码就是获取监听结果。

  这是最简单和最精简的Socket通讯原理,基于这个核心点我们来开发一个简易的,可以提供静态页面访问的 custom tomcat,准备一个index.html文件放到/home/webroot目录下,那么除去拓展上面代码外,我们还需要一个Response和一个Request

  类设计如下:

  HttpServer: 主函数所在类,负载启动ServerSocket和 操作整合Socket监听到的数据,以及返回结果,即操作ResponseRequest

  Request: 封装Socket监听到的用户端请求,包括请求的http uri信息。

  Response: 封装需要推送到客户端的结果数据,即我们需要根据http uri 去本机寻找相应的资源,写给客户端。

  言简意赅,进入代码,首先 Request类代码:

 

复制代码
 1 public class Request 
 2 {
 3     private InputStream input;
 4     private String uri;
 5     
 6     public Request(InputStream input) {
 7         this.input = input;
 8     }
 9     
10     public void parse()
11     {
12         StringBuffer request = new StringBuffer(2048);
13         int i;
14         byte[] buffer = new byte[2048];
15         try
16         { 
17              i = input.read(buffer);
18         }
19         catch(IOException e) 
20         { 
21              e.printStackTrace(); 
22              i = -1; 
23         }
24 
25         for (int j=0; j<i; j++) 
26         {
27             request.append((char) buffer[j]);
28         } 
29         System.out.print(request.toString()); 
30         uri = parseUri(request.toString());
31     }
32     
33     private String parseUri(String requestString) 
34     {  
35         int index1, index2; 
36         index1 = requestString.indexOf(' ');
37         if (index1 != -1) { 
38             index2 = requestString.indexOf(' ', index1 + 1);
39             if (index2 > index1) 
40                 return requestString.substring(index1 + 1, index2); 
41             }  
42         return null;
43     }
44     
45     public String getUri() 
46     {
47         return uri;
48     }
49 }
复制代码

 

  代码解释:类包括一个属性和两个方法,input属性即是从Socket监听到的信息,Socket会将监听到的信息放入一个InputStream中,我们使用Reqeust类的Input属性来接受。接收到输入流后,在parse中对这个输入流进行解析成字符串,即对Http请求进行拆解,得到完整的Http URL,所以这个方法是私有的,是类存在意义的核心所在,而提供的对外方法parseUri是负载将parse解析的url结果提供给外界,即,客户端发来请求那个文件,具体的是最终提供给Response类,Response类得到这个文件名称后,去本地制定目录读取文件。Tomcat中通常就是webapps目录啦,很熟悉了吧,哈哈。

  Response类如何实现这个读取文件的历史使命呢,代码如下:

 

复制代码
 1 public class Response {
 2 
 3     private static final int BUFFER_SIZE = 1024; 
 4     Request request; 
 5     OutputStream output;
 6     
 7     public Response(OutputStream output) 
 8     { 
 9         this.output = output;
10     }
11 
12     public void setRequest(Request request)
13     {
14         this.request = request;
15     }
16 
17     public void sendStaticResource() throws IOException
18     {
19         byte[] bytes = new byte[BUFFER_SIZE];
20         FileInputStream fis = null;
21         try 
22         {
23                 File file = new File(HttpServer.WEB_ROOT, request.getUri());
24                 if (file.exists())
25                 { 
26                         fis = new FileInputStream(file); 
27                         int ch = fis.read(bytes, 0, BUFFER_SIZE); 
28                         while (ch!=-1) { 
29                             output.write(bytes, 0, ch); 
30                             ch = fis.read(bytes, 0, BUFFER_SIZE);
31                         }
32                 }
33                 else 
34                 {
35                     String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
36                         "Content-Type: text/html\r\n" + 
37                         "Content-Length: 23\r\n" +
38                         "\r\n" +
39                         "<h1>File Not Found</h1>";
40                     output.write(errorMessage.getBytes());
41                 }
42         }
43         catch(Exception e) 
44         {
45                 System.out.println(e.toString());
46         }
47         finally{
48             fis.close();
49         }
50  
51     }
52 }
复制代码

 

  代码解释:Response一共三个属性,一个方法。三个属性,一个是设置属性,BUFFER_SIZE设置读写字节流大小,关于读写文件,我个人觉得和服务器的性能和程序性能息息相关,不宜设定过大或过小(此处有不同见解的同仁欢迎来喷,我对这块理解目前限于此)。Reqeust属性,对照前文呼应,Response需要获取Request类的uri结果信息,所以这里放了一个Request属性,获取uriOutput,就不用说了,也是这个类存在的核心意义,依照Request类提供的uri信息,在本地读写文件后,形成一个输出来,存放到output中,那么这项工作就由sendStaticResource这个共有方法完成啦。

  好,代码到这个,可以说我们大家已经看到一个tomcat模型了,有点万事俱备,只欠东风的感觉,客户端发起请求,ResponseReqeust有了,那么继续往上游考虑,Reqeust依赖于客户端的请求,自然以来于Socket数据。我们在这里做得简便一点,将ServerSocketSocket封装到一个HttpServer类中来,代码如下:

 

复制代码
 1 public class HttpServer {
 2     
 3     public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";
 4     private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
 5     private boolean shutdown = false;
 6     public static void main(String[] args)
 7     {
 8         HttpServer httpServer = new HttpServer();
 9         httpServer.await();
10     }
11             
12     public void await()
13     {
14         ServerSocket serverSocket = null;
15         Integer port = 8080; 
16         try 
17         { 
18             serverSocket =  new ServerSocket(port, 1, InetAddress.getByName("10.10.10.106")); 
19         } 
20         catch(IOException e)     
21         { 
22             e.printStackTrace(); 
23             System.exit(1); 
24         } 
25         
26         while(!shutdown)
27         {
28             Socket socket = null;
29             InputStream input = null;
30             OutputStream output = null;
31             try 
32             { 
33                 socket = serverSocket.accept();
34                  
35                 input = socket.getInputStream(); 
36                 output = socket.getOutputStream(); 
37                 Request request = new Request(input); 
38                 request.parse(); 
39                 Response response = new Response(output);
40                 response.setRequest(request); response.sendStaticResource();  socket.close(); 
41                 shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
42             }
43             catch(Exception e) 
44             {
45                 e.printStackTrace();continue;
46             }
47         }
48     }
49 }
复制代码

 

  代码解释:我们知道启动tomcat之后,只要服务正常,客户端任意时候发起一个http请求,tomcat就会响应,那么这里我们肯定需要一个while循环来模拟不间断的监听,类await方法就是负责不断的获取socket监听到的结果,有立刻调动ReqeustResponse进行响应,加入主函数,为的是我们这个是模拟的控制台程序,需要一个程序入口,main函数就是程序入口。此外,HttpServer类包括一个静态属性SHUTDOWN_COMMAND,输入为true则停止这个main函数,变量初始值为false,当客户端也就是Request响应得到客户端输入 http://10.10.10.108:8080/SHUTDOWN时候,则变量在while中会置成true,紧接着停止main,结束应用程序进程。

  在eclipse中或者在命令行中启动这个main函数,命令行则是输入 java HttpServer.javaeclipse则是在main函数中右键 run as application启动。我们打开浏览器,输入 http://10.10.10.108:8080/index.html,回车结果如下:

  本地文件:

  

  好了,夜深啦,就此搁笔了,抛砖引玉,欢迎提议和讨论,这个系列会继续下去,直到一个完整的可以响应一个java action请求的custom tomcat产品出来。

 

其他精彩文章

android学习笔记(41)android选项菜单和子菜单(SubMenu )

android学习笔记(40)Notification的功能与用法

android学习笔记(42)android使用监听器来监听菜单事件

android学习笔记(43)android创建单选菜单和复选菜单

 

更多关于android开发文章

2
4
分享到:
评论
2 楼 cywhoyi 2015-01-14  
yunpheng 写道
这是单线程模型,并发请求会阻塞

它这个是老版本,我那个时候看得也是这个,疑问很多,后来发现那时的tomcat为何瓶颈那么大
1 楼 yunpheng 2015-01-14  
这是单线程模型,并发请求会阻塞

相关推荐

    迷你版的Tomcat,socket原理

    迷你版的Tomcat是一个小型化的Java Web服务器,它实现了HTTP服务器的基本功能,允许开发者在本地环境中部署和运行简单的Web应用程序。这个项目的核心是基于Socket编程,通过Java的Socket类来处理客户端的请求并发送...

    tomcat工作原理(中文版)

    本文旨在深入探讨Tomcat的工作原理,尤其关注其内部机制如何支持Web应用的运行。目标读者是对Java Web开发感兴趣的开发者和技术爱好者。接下来,我们将逐步了解Tomcat的基本组成部分及其功能。 #### 二、Servlet...

    apache-tomcat-8.5.9-src

    【Apache Tomcat 8.5.9 源码解析】 Apache Tomcat 是一个开源的、免费的应用服务器,主要用于部署Java Servlet 和 JavaServer Pages (JSP) 应用程序。这个压缩包 "apache-tomcat-8.5.9-src" 包含了Tomcat 8.5.9 ...

    tomcat的工作原理

    《深入解析Tomcat的工作原理》 一、简介与概览 Apache Tomcat是基于Java的开源Web服务器,它不仅能够运行Java Servlet,还能部署和执行Java Server Pages (JSP)技术,以及支持Java Web应用程序所需的其他标准协议...

    tomcat源码解析

    - **Service**:包含一个Connector和一个Container,用于定义一个可以独立运行的“虚拟”服务器。 - **Engine**:代表一个名称空间,通常对应于主机名。 - **Host**:代表一个虚拟主机,在一个Engine下可以有多个...

    tomcat connectors

    如果你需要深入理解Tomcat连接器的工作原理,或者想要对其进行定制,你可以编译这个源代码。这通常涉及到下载源码,配置构建环境(如Apache Maven或Ant),然后执行构建命令来生成可部署的二进制文件。 了解Tomcat ...

    tomcat 中运行php 环境的jar包

    它的工作原理是通过启动一个内部的PHP进程,然后通过Java的Socket通信来传递请求和响应。 2. **php-script.jar**:这个JAR文件可能包含用于处理PHP脚本的特定实现,它可以解析PHP文件,并将PHP代码转换为Java可以...

    how tomcat workd tomcat工作原理

    通过这样的一本书,你可以更深入地了解Tomcat的工作原理,从最基本的socket服务端和客户端开始,逐步扩展,最终完成一个简单的servlet容器。这将帮助你彻底搞懂Tomcat,不仅可以使用它,还可以对它进行更深层次的...

    11. 计算机网络编程(Socket)思维导图

    计算机网络编程是软件开发中的重要领域,特别是在分布式系统和互联网应用中。Socket编程是实现网络通信的基础,它为应用程序提供了一...理解Socket连接机制和Tomcat的工作原理,对于开发高效、稳定的网络应用至关重要。

    Tomcat-4.1.31.rar

    本篇文章将深入探讨Tomcat 4.1.31版本,解析其核心概念、设计原理以及实际应用中的关键点。 一、Tomcat概述 Tomcat起源于1999年,由James Duncan Davidson开发,最初是为了提供一个轻量级的Servlet容器。4.1.31...

    how-tomcat-works中文 doc文档

    ### Tomcat工作原理详解 #### 一、简介与概览 Tomcat作为一款开源的Servlet容器,被广泛应用于Java Web开发之中。它不仅能够运行Java Servlet,还支持JSP技术,是学习Java Web开发的理想平台之一。本文档将对...

    Tomcat工作原理

    - 在Tomcat运行时,可以直接替换或添加Web应用目录中的文件,Tomcat会自动检测并重新加载变化。 10. **集群与负载均衡** - 对于高可用性需求,Tomcat支持集群配置,可以实现请求在多个Tomcat实例之间进行负载均衡...

    how-tomcat-works.docx

    《深入理解Tomcat工作原理》 Tomcat是Apache软件基金会的Jakarta项目中的一个核心项目,是一个开源的、免费的Web应用服务器,广泛应用于中小型企业的Web应用程序部署。它基于Java Servlet和JavaServer Pages(JSP)...

    分析Tomcat的工作原理

    Tomcat是一个广泛使用的开源Java应用...总之,Tomcat是一个功能强大的Web服务器,其工作原理包括连接器的网络通信和容器的请求处理。掌握这些原理不仅有助于日常开发,还能提升解决问题的能力,为职业生涯增添亮点。

    web监听端口(Socket服务随web启动而启动)

    本文将详细解析"web监听端口(Socket服务随web启动而启动)"这一主题,涵盖Socket、Tomcat服务器以及Web服务的监听端口设置。 首先,让我们了解Socket。Socket是计算机网络中的一个概念,它提供了一种进程间通信(IPC...

    Tomcat的原理及架构.docx

    Tomcat是一款广泛使用的开源Java应用服务器,特别适合于运行Servlet和JSP应用。它的核心架构设计基于组件模型,其中最重要的是Server、Service、Connector和Container这四个关键组件。 1. Server:作为Tomcat的顶级...

    how-tomcat-works中文版

    本篇文章将深入探讨Tomcat的工作原理,通过一系列章节帮助读者理解这个强大的Web服务器的内部机制。 第1章:一个简单的Web服务器 在这个章节,我们将从基础的HTTP协议开始,了解它是如何驱动Web服务器与浏览器之间...

    tomcat简单实现

    本篇将深入探讨如何通过Socket编程和反射技术来简单实现一个基础的Tomcat服务器。 首先,让我们了解Socket编程在Tomcat中的作用。在计算机网络中,Socket是进程间通信的一种方式,它是基于TCP/IP协议进行通信的基础...

Global site tag (gtag.js) - Google Analytics