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

Java代码  

  1. package chapter1.simplewebserver;
  2. import java.io.File;
  3. import java.io.InputStream;
  4. import java.io.OutputStream;
  5. import java.net.InetAddress;
  6. import java.net.InterfaceAddress;
  7. import java.net.ServerSocket;
  8. import java.net.Socket;
  9. /**
  10. *
  11. *  下午11:59:29
  12. * @author gogole_09
  13. * 简单web服务器
  14. */
  15. public class HttpServer {
  16. //定位到webroot目录
  17. public static final String WEB_ROOT=System.getProperty("user.dir")+File.separator+"webroot";
  18. //停止命令
  19. private static final String SHUTDOWN_COMMAND="/SHUTDOWN";
  20. //是否接收到了关闭命令
  21. private boolean shutdown=false;
  22. /**
  23. * 等待命令
  24. */
  25. public void await(){
  26. ServerSocket serverSocket=null;
  27. int port=8090;
  28. try {
  29. serverSocket=new ServerSocket(port,1,InetAddress.getByName("127.0.0.1"));
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. System.exit(1);
  33. }
  34. //监听端口,等待请求。
  35. while(!shutdown){
  36. Socket socket=null;
  37. InputStream input=null;
  38. OutputStream output=null;
  39. try {
  40. socket=serverSocket.accept();
  41. //输入流 有过jsp编程的哥们都知道这是干嘛的
  42. input=socket.getInputStream();
  43. //输出流
  44. output=socket.getOutputStream();
  45. //构建请求
  46. Request request=new Request(input);
  47. //解析请求信息
  48. request.parse();
  49. //响应类
  50. Response response=new Response(output);
  51. response.setRequest(request);
  52. response.sendStaticResource();
  53. //处理完毕,关闭
  54. socket.close();
  55. //检查提供的URI是否为shutdown命令
  56. shutdown=request.getUri().equals(SHUTDOWN_COMMAND);
  57. } catch (Exception e) {
  58. e.printStackTrace();
  59. continue;
  60. }
  61. }
  62. }
  63. public static void main(String[] args) {
  64. HttpServer server=new HttpServer();
  65. server.await();
  66. }
  67. }

接下来是请求类:

Request

Java代码  

  1. package chapter1.simplewebserver;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. /**
  5. *
  6. *  上午12:09:36
  7. * @author gogole_09
  8. *  简单服务器的请求类
  9. */
  10. public class Request {
  11. private InputStream input;
  12. private String uri;
  13. public Request(InputStream in) {
  14. this.input=in;
  15. }
  16. /**
  17. * 解析Uri操作
  18. */
  19. public void parse() {
  20. StringBuffer buf=new StringBuffer();
  21. int i;
  22. byte[] buffer=new byte[2048];
  23. try {
  24. i=input.read(buffer);
  25. } catch (IOException e) {
  26. e.printStackTrace();
  27. i=-1;
  28. }
  29. for(int j=0;j<i;j++){
  30. buf.append((char)buffer[j]);
  31. }
  32. System.out.println(buf.toString());
  33. uri=parseUri(buf.toString());
  34. }
  35. /**
  36. * 解析Uri
  37. *  为什么要以‘ ‘为做标识 , 这里需要了解HTTP协议的相关结构;
  38. *   一个请求行 以 请求方法开头 + 请求URI+ 请求协议版本 + CRLF字符结束
  39. *    比如,你请求index.html 用GET方式 ,那么Uri形式为:
  40. *
  41. *    GET /index.html HTTP/1.1
  42. *
  43. *
  44. * @param requestString
  45. * @return
  46. */
  47. private String parseUri(String requestString){
  48. int index1,index2;
  49. index1=requestString.indexOf(‘ ‘);
  50. if(index1!=-1){
  51. index2=requestString.indexOf(‘ ‘,index1+1);
  52. if(index2>index1){
  53. return requestString.substring(index1+1,index2);
  54. }
  55. }
  56. return null;
  57. }
  58. public String getUri() {
  59. return uri;
  60. }
  61. }

有了请求了,服务器就得响应啊,试想,我发个请求没反应,你的第一反应是不是想砸电脑呢?

OK,Response类来了。

Java代码  

  1. package chapter1.simplewebserver;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.OutputStream;
  6. /**
  7. *
  8. * 上午12:10:58
  9. *
  10. * @author gogole_09 简易服务器的响应类
  11. */
  12. public class Response {
  13. /**
  14. * HTTP响应格式:= Status-Line
  15. * *((general-header|response-header|entity-header)CRLF) CRLF [message-body]
  16. * Status-Line=HTTP-Version SP(空格) Status-Code SP Reason-Phrase CRLF
  17. *
  18. */
  19. private static final int BUFFER_SIZE = 1024;
  20. Request request;
  21. private OutputStream output;
  22. public Response(OutputStream output) {
  23. this.output = output;
  24. }
  25. public void setRequest(Request request) {
  26. this.request = request;
  27. }
  28. /**
  29. * 服务器解析并发送静态资源
  30. * @throws IOException
  31. */
  32. public void sendStaticResource() throws IOException {
  33. byte[] bytes = new byte[BUFFER_SIZE];
  34. FileInputStream fis = null;
  35. try {
  36. File file = new File(HttpServer.WEB_ROOT, request.getUri());
  37. if (file.exists()) {
  38. fis = new FileInputStream(file);
  39. int ch = fis.read(bytes, 0, BUFFER_SIZE);
  40. while (ch != -1) {
  41. output.write(bytes, 0, ch);
  42. ch = fis.read(bytes, 0, BUFFER_SIZE);
  43. }
  44. } else {
  45. //文件没找到
  46. String errorMessage = "HTTP/1.1 404 File Not Found\r\n"
  47. + "Content-Type:text/html\r\n"
  48. + "Content-Length:23\r\n"+"\r\n<ht>File Not Found</h1>";
  49. output.write(errorMessage.getBytes());
  50. }
  51. } catch (Exception e) {
  52. System.out.println(e.toString());
  53. }finally{
  54. if(fis!=null)
  55. fis.close();
  56. }
  57. }
  58. }

OK,现在这个应用可以运行了,但是你运行起来,没办法用,为什么, 因为还需要有用户请求的静态资源。

在HttpServer类中,我们hard code了一个webroot目录,约定把所有的静态资源都放到这个目录下面的。

下面我们就把这个目录建好,并放一点资源进去 ,我是这样放的, 如图:

index.html 中 就只有一行代码:

OK, 下面我们运行一下 HttpServer ,得到页面 如下图:

在控制台,你将会看到程序打印出:

接着,我们尝试请求一个不存在的资源:   我们会的到一个404的错误页面.

OK, 一个简单的web服务器就完成了, 虽然简单,但是我们可以通过这个了解一个大概的流程。

以及复习一下java net包与HTTP/1.1协议的一些知识。

也希望这个篇文章对都有需要的人有帮助。

PS: 最近有很多朋友都问这本书哪里有买,我本人并非看的纸质的,而是电子版的, 需要下载的可以去新浪共享频道找找, 我的是从哪里下来的, 中文书名就叫 <tomcat工作原理>

分享到:  

Java虚拟机简述 | Tomcat解析之初始化类加载器(截图)

评论

14 楼 nbnxyuyun 2010-06-12

public static final String WEB_ROOT=System.getProperty("user.dir")+File.separator+"webroot";中user.dir如何设,我试了无法侦测到8090端口.

13 楼 sw1982 2010-03-26

刚好受这个帖子推荐看到shutdownhook这个玩意,可是这个东东只能处理本身正在运行的进程退出。 
现在的场景是我用sh脚本nohup启动一个java进程后台运行,然后怎么友好关闭这个线程呢?  最简单的就是向一个端口发stop请求。

gogole_09 写道

sw1982 写道

比较精华的地方是启动、关闭操作。。 
占用一个port监听关闭命令,呵呵。 这里可以对java项目的友好关闭做一下处理

这个port监听不止是单独处理关闭,所有的请求都通过端口的,只是为了简单,根据URI来确定是否关闭。 实际在tomcat内部,还用到了ShutDownHook这个东西来处理 tomcat的关闭。 有兴趣的可以看看how tomcat works的ShutDownHook这个章节。 呵呵, 欢迎交流。

12 楼 gogole_09 2010-03-25

sw1982 写道

比较精华的地方是启动、关闭操作。。
占用一个port监听关闭命令,呵呵。 这里可以对java项目的友好关闭做一下处理

这个port监听不止是单独处理关闭,所有的请求都通过端口的,只是为了简单,根据URI来确定是否关闭。 实际在tomcat内部,还用到了ShutDownHook这个东西来处理 tomcat的关闭。 有兴趣的可以看看how tomcat works的ShutDownHook这个章节。 呵呵, 欢迎交流。

11 楼 gogole_09 2010-03-25

mercyblitz 写道

Tomcat 不也是处理Socket吗?

tomcat内部也是处理socket的, 不知有什么不对吗?

10 楼 sw1982 2010-03-22

比较精华的地方是启动、关闭操作。。 
占用一个port监听关闭命令,呵呵。 这里可以对java项目的友好关闭做一下处理

9 楼 mercyblitz 2010-03-22

Tomcat 不也是处理Socket吗?

8 楼 fantasybei 2010-02-18

也没你说得那么好,一般般吧,有些东西说得太罗嗦.

7 楼 hellojinjie 2010-02-16

为何不用 NIO 来实现呢,,

6 楼 smartman_jc 2010-02-10

不错!学习了,受益匪浅

5 楼 gogole_09 2010-02-08

wanggp 写道

应该是how tomcat works

嘿嘿,是的。 书名写错了,马上修正。

4 楼 elgs 2010-02-07

how tomcat works在中国买不到,这么好的书。

3 楼 wanggp 2010-02-07

应该是how tomcat works

2 楼 gogole_09 2010-02-06

曾经de迷茫 写道

请问楼主浏览器上装的什么东东,看请求资源的那个?

是Http Watch. 查看请求url,传递的参数,以及服务器返回数据的好东西。

1 楼 曾经de迷茫 2010-02-06

请问楼主浏览器上装的什么东东,看请求资源的那个?

时间: 2024-11-06 04:28:34

tomcat解析之简单web服务器(图)的相关文章

Socket实现简单Web服务器

上一篇博客中介绍了怎样使用socket访问web服务器.关键有两个: 1)熟悉Socket编程: 2)熟悉HTTP协议. 上一篇主要是通过socket来模拟浏览器向(任何)Web服务器发送(HTTP)请求,重点在浏览器端.本篇博客则反过来讲一下怎样使用socket来实现Web服务器,怎样去接收.分析.处理最后回复来自浏览器的HTTP请求. HTTP协议是浏览器和Web服务器都需要遵守的一种通信规范,如果我们编写一个程序,正确遵守了HTTP协议,那么理论上讲,这个程序可以具备浏览器.甚至Web服务

【Web后端笔记】基于Socket实现的简单Web服务器搭建

我们在地址栏中输入的内容称为通用资源标记符(Universal Resource Identifier,URI)它有很多种样式,在Web中我们通常称为统一资源定位符(Uniform Resource Locator,URL)的形式,它的格式如下: 协议://主机[.端口号][绝对路径[?参数]] 在http://www.cnblogs.com/DebugLZQ/中,http表示协议名称;www.cnblogs.com表示主机的地址:可选的端口号没有出现,那么,将使用http协议默认的端口号80:

Socket网络编程--简单Web服务器(1)

这一次的Socket系列准备讲Web服务器.就是编写一个简单的Web服务器,具体怎么做呢?我也不是很清楚流程,所以我找来了一个开源的小的Web服务器--tinyhttpd.这个服务器才500多行的代码,使用C语言.这一小节就不讲别的内容了.就对这个程序进行一些注释和讲解了. 主函数: 1 int main(void) 2 { 3 int server_sock = -1; 4 u_short port = 0; 5 int client_sock = -1; 6 struct sockaddr_

java实现简单web服务器(分析+源代码)

在日常的开发中,我们用过很多开源的web服务器,例如tomcat.apache等等.现在我们自己实现一个简单的web服务器,基本的功能就是用户点击要访问的资源,服务器将资源发送到客户端的浏览器.为了简化操作,这里不考虑资源不存在等异常情况.web服务基于的是HTTP协议,用户在浏览器的地址栏输入要访问的地址,服务器如何得到该地址是个关键.先看下一般的HTTP请求和响应报文的一般格式: HTTP 请求报文 HTTP 响应报文 web服务器获取一个用户的连接时,会初始化一个线程和用户通信,代码如下:

一个基于AIO实现的简单web服务器

一下是一个基于AIO实现的简单web服务器,这是一个简单例子 /** * 一个简单的web 服务器<br/> * 通过浏览器输入localhost:8080/访问 * * @author Joeson * @since 2014/05 * */ public class AioServer implements Runnable { private AsynchronousChannelGroup asyncChannelGroup; private AsynchronousServerSoc

我叫Tomcat:一款web服务器

我叫Tomcat:一款web服务器 如何将我们的 Java 代码,运行在网络上,初学时,首先接触到的一般都是Servlet以及Jsp(或略过Jsp)而 Tomcat 就是这两者的容器,帮你处理动态网页部分 (一) 从哪来,到哪去? (1) Tomcat和它的小伙伴 JBoss:Redhat 红帽,支持所有的 JavaEE 规则,适合大型项目,收费 Weblogic:Orcale,支持所有 JavaEE 规则,适合大型项目,收费 Websphere:IBM,支持所有 JavaEE 规则,适合大型项

C#中使用Socket实现简单Web服务器

原文地址:https://www.cnblogs.com/mq0036/p/6656888.html 最近有个web的小项目,但公司的电脑无法安装IIS,所以就想自己来实现个Web server服务器,原本想了下,也就是socket处理http请求,于是就在博客园中搜索了"socket实现web server",结果还真搜索到一些文章,于是从中找了几个做参考,如下: C#中使用Socket实现简单Web服务器 C#中使用Socket模拟请求Web服务器过程 C#中自己动手创建一个Web

Python 实现简单 Web 服务器

Python 实现简单 Web 服务器 最近有个需求,就是要创建一个简到要多简单就有多简单的web服务器,目的就是需要一个后台进程用来接收请求然后处理并返回结果,因此就想到了使用python来实现. 首先创建一个myapp.py文件,其中定义了一个方法,所有的请求都会经过此方法,可以在此方法里处理传递的url和参数,并返回结果. def myapp(environ, start_response): status = '200 OK' headers = [('Content-type', 't

自己实现简单Web服务器,支持GET POST请求

最近项目上遇到一个需求,最后想到的解决方案是自己实现一个web服务器去处理请求,然后再将信息发送到另外一个程序.然后返回处理之后的结果呈现出来. 现在我就来分享一下如何实现的. 通过.NET 为我们提供的HttpListener类实现对Http协议的处理,实现简单的web服务器. 注意:此类在 .NET Framework 2.0 版中是新增的.所以支持.NET Framework 2.0以上版本.该类仅在运行 Windows XP SP2 或 Windows Server 2003 操作系统的