tomcat(1)一个简单的web server

【0】README

0.1)本文部分描述转自“深入剖析tomcat”, 旨在学习  一个简单的web server  的基础知识;

0.2)for complete source code, please visit https://github.com/pacosonTang/HowTomcatWorks/tree/master/chapter1


【1】HTTP

【1.1】HTTP请求
1)一个HTTP请求包括以下3部分(parts):(干货——一个HTTP请求包括以下3部分(parts))
p1)请求方法——统一资源标识符(URI)——协议/版本;
p2)请求头;
p3)实体;
2)HTTP 请求的示例如下所示:(干货——HTTP请求代码荔枝)
Post /examples/default.jsp HTTP/1.1
Accept: text/plain; text/html
Accept-Language: en-gb 
Connection: Keep-Alive
Host: localhost
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
Content-Length: 33
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
// 这里是空行(CRLF)
lastName=Yun&firstName=Lin
对以上HTTP请求的分析(Analysis):(干货——对HTTP请求的分析)
A1)第一行:请求方法——URI——协议/版本(Post /examples/default.jsp HTTP/1.1)
A2)HTTP1.1 支持的请求方法有:GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE;
A3)URI:指定internet 资源的完整路径;而统一资源定位符(URL) 是 URI 的一种类型;
A4)在请求头和请求实体间有一个空行:该空行只有 CRLF 符;CRLF 告诉HTTP 服务器请求实体正文从哪里开始;正文(lastName=Yun&firstName=Lin)

【1.2】HTTP响应
1)HTTP响应也包括3部分(parts):
part1)协议——状态码——描述;
part2)响应头;
part3)响应实体段;
2)HTTP响应的荔枝,如下所示:
HTTP/1.1 200 OK
Server: Microsoft-IIS/4.0
Date: Mon, 5 Jan 2004 13:13:33 GMT
Content-Type: text/html
Last-Modified: Mon, 5 Jan 2004 13:13:12 GMT
Content-Length: 112
//空行(CRLF)
<html>
<head>
<title>hello, world</title>
</head>
<body>
hello, world
</body>
</html>
对上述HTTP响应代码的分析(Analysis):
A1)第一行的200,表示状态码(请求发送成功);
A2)响应头和响应实体正文间由只包含 CRLF 的一个空行分隔;
【1.3】Socket类
1)看个荔枝:(创建一个套接字,用于与本地HTTP Server 进行通信(127.0.0.1 表示一个本地主机),发送HTTP请求接收server 的响应信息);
// 创建一个套接字,用于与本地HTTP Server 进行通信(127.0.0.1 表示一个本地主机),发送HTTP请求接收server 的响应信息
// 采用tomcat 开启8080 端口
public class SocketTest {public static void main(String[] args) throws Exception {try(Socket socket = new Socket("127.0.0.1", 8080)){OutputStream os = socket.getOutputStream();boolean autoflush = true;PrintWriter out = new PrintWriter(socket.getOutputStream(), autoflush);BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));// send an HTTP request to the web serverout.println("GET /index.jsp HTTP/1.1");out.println("Host: localhost:8080");out.println("Connection: Close");out.println();// read the responseboolean loop = true;StringBuffer sb = new StringBuffer(8096);while(loop) {if(in.ready()) {int i = 0;while(i != -1) {i = in.read();sb.append((char)i);}loop = false;}Thread.currentThread().sleep(50);}// display the response to the out consoleSystem.out.println(sb.toString());socket.close();}}
}


【3】应用程序
0)intro:web服务器应用程序包括3个类: HttpServer, Request, Response;
1)我们先看运行结果(显然发出了两个HTTP 请求,浏览器发出一个获取静态资源的 HTTP请求, 而该静态资源又 发出获取图像资源的 HTTP 请求)(干货——显然发出了两个HTTP 请求
E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src>java com.tomcat.chapter1.HttpServer
E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src
GET /index.html HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6GET /images/psu.jpg HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Accept: image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Referer: http://localhost:8080/index.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6GET /SHUTDOWN HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6

2)HttpServer, Request, Response 的源码如下所示:
public class HttpServer { // 接受HTTP 请求的web server/** WEB_ROOT is the directory where our HTML and other files reside.*  For this package, WEB_ROOT is the "webroot" directory under the working*  directory.*  The working directory is the location in the file system*  from where the java command was invoked.*/public static final String WEB_ROOT =System.getProperty("user.dir") + File.separator  + "webroot";// shutdown commandprivate static final String SHUTDOWN_COMMAND = "/SHUTDOWN";// the shutdown command receivedprivate boolean shutdown = false;public static void main(String[] args) {System.out.println(System.getProperty("user.dir"));HttpServer server = new HttpServer();server.await();// 会在指定端口上等待HTTP请求。}public void await() {ServerSocket serverSocket = null;int port = 8080;try {serverSocket =  new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));}catch (IOException e) {e.printStackTrace();System.exit(1);}// Loop waiting for a requestwhile (!shutdown) {Socket socket = null;InputStream input = null;OutputStream output = null;try {socket = serverSocket.accept();input = socket.getInputStream();output = socket.getOutputStream();// create Request object and parse,创建 HTTP请求对象Request request = new Request(input);request.parse(); // 解析HTTP请求字符串// create Response object,创建HTTP 响应对象Response response = new Response(output);response.setRequest(request);response.sendStaticResource(); // 发送静态资源到client// Close the socketsocket.close();//check if the previous URI is a shutdown commandshutdown = request.getUri().equals(SHUTDOWN_COMMAND);}catch (Exception e) {e.printStackTrace();continue;}}}
}
public class Request { // 封装 HTTP 请求字符串的类private InputStream input;private String uri;public Request(InputStream input) {this.input = input;}public void parse() {// Read a set of characters from the socketStringBuffer request = new StringBuffer(2048);int i;byte[] buffer = new byte[2048];try {i = input.read(buffer);}catch (IOException e) {e.printStackTrace();i = -1;}for (int j=0; j<i; j++) {request.append((char) buffer[j]);}System.out.print(request.toString());uri = parseUri(request.toString());}private String parseUri(String requestString) {int index1, index2;index1 = requestString.indexOf(' ');if (index1 != -1) {index2 = requestString.indexOf(' ', index1 + 1);if (index2 > index1)return requestString.substring(index1 + 1, index2);}return null;}public String getUri() {return uri;}}
public class Response {  <span style="font-family: 宋体;">// 封装 HTTP 响应字符串的类</span>private static final int BUFFER_SIZE = 1024;Request request;OutputStream output;public Response(OutputStream output) {this.output = output;}public void setRequest(Request request) {this.request = request;}public void sendStaticResource() throws IOException {byte[] bytes = new byte[BUFFER_SIZE];FileInputStream fis = null;try {File file = new File(HttpServer.WEB_ROOT, request.getUri());if (file.exists()) {fis = new FileInputStream(file);int ch = fis.read(bytes, 0, BUFFER_SIZE);while (ch!=-1) {output.write(bytes, 0, ch);ch = fis.read(bytes, 0, BUFFER_SIZE);}}else {// file not foundString errorMessage = "HTTP/1.1 404 File Not Found\r\n" +"Content-Type: text/html\r\n" +"Content-Length: 23\r\n" +"\r\n" +"<h1>File Not Found</h1>";output.write(errorMessage.getBytes());}}catch (Exception e) {// thrown if cannot instantiate a File objectSystem.out.println(e.toString() );}finally {if (fis!=null)fis.close();}}
}
补充)本文总结了一张上述应用程序的调用流程图

对上图的分析(Analysis):
A1)HttpServer:
step1)创建服务器套接字,等待接收 client 发出HTTP 连接请求;
step2)连接成功后,利用套接字创建输入输出流;
step3)创建Request对象, 向Request构造函数传入输入流,并利用request实例对象解析  HTTP  请求;
step4)创建Response对象,向Response构造函数传入输出流,且设置 Response中的request变量引用,调用response对象的sendStaticResource方法发送静态资源到 client;
A2)Request:HTTP请求对象,其parse方法用于读取HTTP请求头;其parseUri方法用于解析client 请求的 uri;
A3)Response:HTTP响应对象,其sendStaticResource方法 读取request解析出的uri对应的资源文件,并发送该文件数据到client端;

3)静态资源html
<html>
<head>
<title>How Tomcat Works</title>
</head>
<body>
<img src="./images/psu.jpg">
<br>
hello, my name is xiao tangtang.
</body>
</html>

4)最后po 出 整体的文件目录架构


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

漫画:什么是MD5算法

转载自 玻璃猫 程序员小灰 摘要哈希生成的正确姿势是什么样呢&#xff1f;分三步&#xff1a; 1.收集相关业务参数&#xff0c;在这里是金额和目标账户。当然&#xff0c;实际应用中的参数肯定比这多得多&#xff0c;这里只是做了简化。 2.按照规则&#xff0c;把参数名和参数…

idea快速生成crud_Java / Spring:如何快速生成完整的Swagger文档CRUD REST API

idea快速生成crud作为开发人员&#xff0c;我们在日常生活中经常面临的最繁琐的任务之一就是编写良好且易于理解的文档。 无论我们的文档只有几行来解释功能的核心功能&#xff0c;还是表明系统的来龙去脉的成熟文章都没关系。 重要的是&#xff0c;我们试图通过文档传达的信息…

漫画:如何破解MD5算法

转载自 玻璃猫 程序员小灰 在之前的漫画中&#xff0c;我们介绍了MD5算法的基本概念和底层原理&#xff0c;没看过的小伙伴们可以点击下面的链接&#xff1a;《漫画&#xff1a;什么是MD5算法&#xff1f;》 这一次&#xff0c;我们来讲解如何破解MD5算法。 设MD5的哈希函数是…

自定义类加载器(ClassLoader + URLClassLoader)

【0】README 0.1&#xff09;本文主要对类加载器进行分析&#xff0c;且 URLClassLoader是 ClassLoader的子类&#xff1b; 0.2&#xff09;关于如何设置类加载器的加载路径&#xff0c;参见 对servlet容器的补充 【1】URLClassLoader类加载器 1.1&#xff09;URLClassLoad…

fork/join和线程池_从fork-join /线程池调用的Singelton bean中的访问spring请求范围缓存...

fork/join和线程池问题&#xff1a; 启用了Spring且其范围设置为Request的缓存需要由不在请求范围内的singleton bean访问。 解&#xff1a; Spring使您能够创建缓存&#xff0c;该缓存为请求范围保留数据。 例如 import org.springframework.cache.concurrent.ConcurrentMapC…

tomcat(2)一个简单的servlet容器

【0】README 0.1&#xff09;本文部分文字转自 “深入剖析Tomcat”&#xff0c;旨在学习 一个简单的servlet容器 的基础知识&#xff1b; 0.2&#xff09;for complete source code, please visit https://github.com/pacosonTang/HowTomcatWorks/tree/master/chapter2 0…

漫画:什么是Base64算法

转载自 玻璃猫 程序员小灰 ValueChar ValueChar ValueChar ValueChar0A16Q32g48w1B17R33h49x2C18S34i50y3D19T35j51z4E20U36k5205F21V37l5316G22W38m5427H23X39n5538I24Y40o5649J25Z41p57510K26a42q58611L27b43r59712M28c44s60813N29d45t61914O30e46u6215P31f47v63/控制字符&am…

soapui 测试soap_使用SoapUI调用不同的安全WCF SOAP服务-基本身份验证,第一部分

soapui 测试soap在这个分为三部分的系列中&#xff0c;我将演示如何使用SoapUI API工具来调用安全的WCF SOAP服务。 第一篇文章将着重于创建将要测试的系统的服务。 第二篇文章将介绍在基本身份验证机制保护的情况下调用它所需的步骤。 在最后一部分中&#xff0c;我将对初始服…

dmn是大脑中哪个区域_DMN中的函数式编程:感觉就像再次重读我的大学课程一样...

dmn是大脑中哪个区域在本文中&#xff0c;我想分享有关DMN中递归支持的有趣见解&#xff0c;并重点介绍FEEL语言的特定属性如何使功能性编程结构能够在DMN中建模。 我们将从一个基本示例开始&#xff0c;以演示FEEL语言和DMN构造的“商业友好”性质如何使我们能够解决一个通常…

对Servlet容器的补充

【0】README 0.1&#xff09;本文是对 一个简单的servlet容器 的补充&#xff1b; 【1】Servlet容器 1.1&#xff09;通过一个简单的servlet容器这篇博文&#xff0c;我们看到&#xff1a;其中的核心代码是 类加载器&#xff0c; 然而&#xff0c;在我follow 其代码&#xf…

漫画:什么是A*寻路算法

转载自 玻璃猫 程序员小灰比如像这样子&#xff1a;第一步&#xff1a;把起点放入OpenList第二步&#xff1a;找出OpenList中F值最小的方格&#xff0c;即唯一的方格Node(1,2)作为当前方格&#xff0c;并把当前格移出OpenList&#xff0c;放入CloseList。代表这个格子已到达并…

apache ignite_Kubernetes集群上的Apache Ignite和Spring第2部分:Kubernetes部署

apache ignite以前&#xff0c;我们已经成功创建了第一个由Apache Ignite支持的Spring boot Application。 在此博客上&#xff0c;我们将重点介绍Kubernetes方面需要做的事情&#xff0c;以便能够启动我们的应用程序。 如先前博客所述&#xff0c;我们需要制定我们的Kuberne…

漫画:什么是布隆算法

转载自 玻璃猫 程序员小灰两周之前——爬虫的原理就不细说了&#xff0c;无非是通过种子URL来顺藤摸瓜&#xff0c;爬取出网站关联的所有的子网页&#xff0c;存入自己的网页库当中。但是&#xff0c;这其中涉及到一个小小的问题......URL去重方案第一版&#xff1a;HashSet 创…

2016第11届四川省高校计算机(软件)院长论坛纪要(旁听)

​【0】README 0.1&#xff09;该论坛与16年4月8日在西南交大召开&#xff0c;为贺西南交大120周年华诞&#xff1b; 0.2&#xff09;以下内容是小生在该论坛上的部分旁听内容&#xff08;仅仅是部分&#xff09;&#xff0c; 感觉很新鲜&#xff0c;故分享之&#xff1b; 0…

selenium自动化测试_为什么在生产中进行Selenium自动化测试对于您的下一个版本至关重要?...

selenium自动化测试您是否认为仅仅是因为您的Web应用程序在过渡环境中以飞快的速度通过&#xff0c;它对于生产环境也将是相同的&#xff1f; 您可能需要重新考虑&#xff01; 特别是&#xff0c;如果我们指的是跨浏览器测试 &#xff0c;则需要确保跨各种操作系统&#xff0c…

java.lang.ExceptionInInitializerError的原因

【0】README 0.1&#xff09;本文转自 http://blog.csdn.net/fykhlp/article/details/6236316&#xff1b; 【1】正文如下 这个错误是说变量初始化出现问题&#xff0c;通常出现在静态变量尤其是单例模式。这种问题往往是初始化顺序不对造成的&#xff0c;下面举个简单的例子。…

漫画:Bitmap算法 整合版

转载自 玻璃猫 程序员小灰两个月之前——为满足用户标签的统计需求&#xff0c;小灰利用Mysql设计了如下的表结构&#xff0c;每一个维度的标签都对应着Mysql表的一列&#xff1a;要想统计所有90后的程序员该怎么做呢&#xff1f;用一条求交集的SQL语句即可&#xff1a;Select…

tomcat(3)连接器

【0】README0.1&#xff09;本文部分内容转自“深入剖析tomcat”&#xff0c;旨在学习 tomcat(3)连接器 的基础知识&#xff1b;0.2&#xff09;Catalina 中有两个主要的模块&#xff1a;连接器&#xff08;ServerSocket&#xff09; 和 容器&#xff08;Servlet容器&#xff0…

java正则表达式验证_如何在Java中验证电话号码(正则表达式+ Google libphonenumber)...

java正则表达式验证关于如何在不同国家&#xff08;例如美国&#xff0c;美国&#xff09;使用Java验证电话号码的快速指南。 带有正则表达式和Google libphonenumber API的示例程序。 1.简介 在本教程中&#xff0c;我们将学习如何在java中验证电话号码 。 这主要是为了验证美…

漫画:什么是B-树

转载自 玻璃猫 程序员小灰 本文提到的「B-树」&#xff0c;就是「B树」&#xff0c;都是 B-tree 的翻译&#xff0c;里面不是减号-&#xff0c;是连接符-。因为有人把 B-tree 翻成 「B-树」&#xff0c;让人以为「B树」和「B-树」是两种树&#xff0c;实际上两者就是同一种树。…