tomcat解析之简单web服务器(图)
链接地址:http://gogole.iteye.com/blog/587163
之前有javaeyer推荐了一本书《how tomcat works》,今天晚上看了看,确实不错,第一眼就着迷了。 于是乎就学着书上的例子敲了敲,学会了一个简单web服务器的大概实现,当然,这个简直就无法称之为web服务器,但是也算是走进web服务器的第一步吧。
这篇文章仅限于学习记录,文笔凌乱之处,还望各位见谅。 OK,下面进入正题;
开始之前,首先我们要清楚以下几个内容。
首先,一个最简单服务器包括三个部分:
web服务器----HttpServer
请求---Request
响应---Response
这个服务器如何使用:
1. 请求静态资源 通过 http://localhost:8090/index.html
成功 则返回页面, 否则会返回 File Not Found 的错误信息.
PS:比如上面的index.html 必须放在一个webroot目录下.
2. 服务器的关闭通过uri来处理
通过http://lcoalhost:8090/SHUTDOWN 这个Uri来停止服务器.
需要注意的其他几个知识点:
1. HTTP/1.1 协议的知识。 比如 请求,响应的结构。 发送与接收形式等.
2. Java中网络的相关只是 ServerSocket 与 Socket 的使用.
OK, 放上代码, 代码只有3个类,都挺简单的, 这个应用只是一个最最简单的雏形:
主类: HttpServer
- package chapter1.simplewebserver;
- import java.io.File;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.InetAddress;
- import java.net.InterfaceAddress;
- import java.net.ServerSocket;
- import java.net.Socket;
- /**
- *
- * 下午11:59:29
- * @author gogole_09
- * 简单web服务器
- */
- public class HttpServer {
- //定位到webroot目录
- public static final String WEB_ROOT=System.getProperty("user.dir")+File.separator+"webroot";
- //停止命令
- private static final String SHUTDOWN_COMMAND="/SHUTDOWN";
- //是否接收到了关闭命令
- private boolean shutdown=false;
- /**
- * 等待命令
- */
- public void await(){
- ServerSocket serverSocket=null;
- int port=8090;
- try {
- serverSocket=new ServerSocket(port,1,InetAddress.getByName("127.0.0.1"));
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(1);
- }
- //监听端口,等待请求。
- while(!shutdown){
- Socket socket=null;
- InputStream input=null;
- OutputStream output=null;
- try {
- socket=serverSocket.accept();
- //输入流 有过jsp编程的哥们都知道这是干嘛的
- input=socket.getInputStream();
- //输出流
- output=socket.getOutputStream();
- //构建请求
- Request request=new Request(input);
- //解析请求信息
- request.parse();
- //响应类
- Response response=new Response(output);
- response.setRequest(request);
- response.sendStaticResource();
- //处理完毕,关闭
- socket.close();
- //检查提供的URI是否为shutdown命令
- shutdown=request.getUri().equals(SHUTDOWN_COMMAND);
- } catch (Exception e) {
- e.printStackTrace();
- continue;
- }
- }
- }
- public static void main(String[] args) {
- HttpServer server=new HttpServer();
- server.await();
- }
- }
接下来是请求类:
Request
- package chapter1.simplewebserver;
- import java.io.IOException;
- import java.io.InputStream;
- /**
- *
- * 上午12:09:36
- * @author gogole_09
- * 简单服务器的请求类
- */
- public class Request {
- private InputStream input;
- private String uri;
- public Request(InputStream in) {
- this.input=in;
- }
- /**
- * 解析Uri操作
- */
- public void parse() {
- StringBuffer buf=new StringBuffer();
- 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++){
- buf.append((char)buffer[j]);
- }
- System.out.println(buf.toString());
- uri=parseUri(buf.toString());
- }
- /**
- * 解析Uri
- * 为什么要以' '为做标识 , 这里需要了解HTTP协议的相关结构;
- * 一个请求行 以 请求方法开头 + 请求URI+ 请求协议版本 + CRLF字符结束
- * 比如,你请求index.html 用GET方式 ,那么Uri形式为:
- *
- * GET /index.html HTTP/1.1
- *
- *
- * @param requestString
- * @return
- */
- 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;
- }
- }
有了请求了,服务器就得响应啊,试想,我发个请求没反应,你的第一反应是不是想砸电脑呢?
OK,Response类来了。
- package chapter1.simplewebserver;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- /**
- *
- * 上午12:10:58
- *
- * @author gogole_09 简易服务器的响应类
- */
- public class Response {
- /**
- * HTTP响应格式:= Status-Line
- * *((general-header|response-header|entity-header)CRLF) CRLF [message-body]
- * Status-Line=HTTP-Version SP(空格) Status-Code SP Reason-Phrase CRLF
- *
- */
- private static final int BUFFER_SIZE = 1024;
- Request request;
- private OutputStream output;
- public Response(OutputStream output) {
- this.output = output;
- }
- public void setRequest(Request request) {
- this.request = request;
- }
- /**
- * 服务器解析并发送静态资源
- * @throws IOException
- */
- 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 {
- //文件没找到
- String errorMessage = "HTTP/1.1 404 File Not Found\r\n"
- + "Content-Type:text/html\r\n"
- + "Content-Length:23\r\n"+"\r\n<ht>File Not Found</h1>";
- output.write(errorMessage.getBytes());
- }
- } catch (Exception e) {
- System.out.println(e.toString());
- }finally{
- if(fis!=null)
- fis.close();
- }
- }
- }
OK,现在这个应用可以运行了,但是你运行起来,没办法用,为什么, 因为还需要有用户请求的静态资源。
在HttpServer类中,我们hard code了一个webroot目录,约定把所有的静态资源都放到这个目录下面的。
下面我们就把这个目录建好,并放一点资源进去 ,我是这样放的, 如图:
index.html 中 就只有一行代码:
OK, 下面我们运行一下 HttpServer ,得到页面 如下图:
在控制台,你将会看到程序打印出:
接着,我们尝试请求一个不存在的资源: 我们会的到一个404的错误页面.
OK, 一个简单的web服务器就完成了, 虽然简单,但是我们可以通过这个了解一个大概的流程。
以及复习一下java net包与HTTP/1.1协议的一些知识。
也希望这个篇文章对都有需要的人有帮助。
PS: 最近有很多朋友都问这本书哪里有买,我本人并非看的纸质的,而是电子版的, 需要下载的可以去新浪共享频道找找, 我的是从哪里下来的, 中文书名就叫 <tomcat工作原理>
![](http://gogole.iteye.com/images/sina.jpg)
![](http://gogole.iteye.com/images/tec.jpg)
评论
现在的场景是我用sh脚本nohup启动一个java进程后台运行,然后怎么友好关闭这个线程呢? 最简单的就是向一个端口发stop请求。
占用一个port监听关闭命令,呵呵。 这里可以对java项目的友好关闭做一下处理
这个port监听不止是单独处理关闭,所有的请求都通过端口的,只是为了简单,根据URI来确定是否关闭。 实际在tomcat内部,还用到了ShutDownHook这个东西来处理 tomcat的关闭。 有兴趣的可以看看how tomcat works的ShutDownHook这个章节。 呵呵, 欢迎交流。
占用一个port监听关闭命令,呵呵。 这里可以对java项目的友好关闭做一下处理
这个port监听不止是单独处理关闭,所有的请求都通过端口的,只是为了简单,根据URI来确定是否关闭。 实际在tomcat内部,还用到了ShutDownHook这个东西来处理 tomcat的关闭。 有兴趣的可以看看how tomcat works的ShutDownHook这个章节。 呵呵, 欢迎交流。
tomcat内部也是处理socket的, 不知有什么不对吗?
占用一个port监听关闭命令,呵呵。 这里可以对java项目的友好关闭做一下处理
嘿嘿,是的。 书名写错了,马上修正。
是Http Watch. 查看请求url,传递的参数,以及服务器返回数据的好东西。
tomcat解析之简单web服务器(图)的更多相关文章
- C#中使用Socket实现简单Web服务器
上一篇博客中介绍了怎样使用socket访问web服务器.关键有两个: 熟悉Socket编程: 熟悉HTTP协议. 上一篇主要是通过socket来模拟浏览器向(任何)Web服务器发送(HTTP)请求,重 ...
- Socket网络编程--简单Web服务器(1)
这一次的Socket系列准备讲Web服务器.就是编写一个简单的Web服务器,具体怎么做呢?我也不是很清楚流程,所以我找来了一个开源的小的Web服务器--tinyhttpd.这个服务器才500多行的代码 ...
- 我叫Tomcat:一款web服务器
我叫Tomcat:一款web服务器 如何将我们的 Java 代码,运行在网络上,初学时,首先接触到的一般都是Servlet以及Jsp(或略过Jsp)而 Tomcat 就是这两者的容器,帮你处理动态网页 ...
- Socket网络编程--简单Web服务器(6)
本来是想实现ssl连接的,但是弄了好久都不成功,就索性不做了,等以后有能力再做了.所以这一小节就是本次的最后一节了.就简单的说几个注意点. 1.加个配置文件 使用单例模式,使用一个类,该类保存一些信息 ...
- Java 18 新特性:简单Web服务器 jwebserver
在今年3月下旬的时候,Java版本已经更新到了18.接下来DD计划持续做一个系列,主要更新从Java 9开始的各种更新内容,但我不全部都介绍,主要挑一些有意思的内容,以文章和视频的方式来给大家介绍和学 ...
- 理解与模拟一个简单web服务器
先简单说下几个概念,根据自己的理解,不正确请见谅. web服务器 首先要知道什么是web服务器,简单说web服务器就是可以使用HTTP传输协议与客户端进行通信的服务器.最初的web服务器只能用来处理静 ...
- java实现简单web服务器(分析+源代码)
在日常的开发中,我们用过很多开源的web服务器,例如tomcat.apache等等.现在我们自己实现一个简单的web服务器,基本的功能就是用户点击要访问的资源,服务器将资源发送到客户端的浏览器.为了简 ...
- Socket网络编程--简单Web服务器(4)
上一小节已经实现了对图片的传输,接下来就是判断文件是否为js,css,png等格式.我们增加一个函数用于判断格式 int WebServer::get_filetype(char *type,char ...
- Socket网络编程--简单Web服务器(5)
这一小节我们将实现服务器对get和post的请求进行对cgi程序的调用.对于web服务器以前的章节已经实现了对get和post请求的调用接口,接下来给出对应接口的实现. int WebServer:: ...
随机推荐
- Linux中ssh的免密码登陆
原理: Hadoop的各个节点要实时的进行各种通信的,ssh就是能让各个节点免密码的相互访问相互通信. 操作步骤: 这里用的加密方式是非对称的加密方式,具体的操作是: <1>执行命令ssh ...
- apache 配置文件管理
1. Apache配置系统 从整体来看apache的配置系统包括三个部分: (1) 配置文件:比如 httpd.conf .htaccess (2) 配置指令:在配置文件 httpd.conf ...
- (Problem 42)Coded triangle numbers
The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); so the first ten triangl ...
- wsdl透明解析
1.逐个分析wsdl文件中的元素: <types>:数据类型定义的容器,一般使用 xml schema类型系统. <message>:通信消息的数据结构的抽象化定义,使用< ...
- 英文论文中“such as, for example, e.g., i.e., etc., et al. ”的用法分析 (转)
在英文论文的编辑加工中,常会遇到such as, for example, e. g. , i. e. , etc. 和et al. 的错误及混淆使用.这里,举例分析这几个词的意义,并阐述其正确用法. ...
- Python+django开发环境搭建
Python目前主版本有2个,2.7+和3.4+ 新入手,决定还是从2.7开始 先从python官网https://www.python.org/下载python2.7.10,64位版本(这里注意,选 ...
- BZOJ 1002 轮状病毒 (基尔霍夫矩阵)
题解:http://vfleaking.blog.163.com/blog/static/17480763420119685112649/ #include <iostream> #inc ...
- LayoutInflater作用是将layout的xml布局文件实例化为View类对象。
获取LayoutInflater的方法有如下三种: LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.L ...
- UVA - 12230 Crossing Rivers (期望)
Description You live in a village but work in another village. You decided to follow the straight pa ...
- java反射机制入门02
Field对象的机制与实现 1.Field对象概述 1)Java.lang.reflect.Field类,是用于表示类中.接口中属性对象的类. 2)可以操作类中私有,以及公有等全部属性和属性的信息. ...