内容为《深入剖析Tomcat》第一章重点,以及自己的总结,如有描述不清的,可查看原书。
一、HTTP协议:
1、定义:用于服务器与客户端的通讯的协议,允许web服务器和浏览器通过互联网进行发送和接收数据。是一种请求和响应协议,使用可靠的TCP协议,TCP协议的端口为80,是一种面向连接的协议。
2、HTTP协议请求的三个组成部分:这三部分之间用回车换行符(CRLF)隔开
     请求部分:方法(GET/POST等7种,其他的很少用,书上有介绍)[空格,该部分内容以空格隔开] 统一资源标识符URI[空格,该部分内容以空格隔开 ] 协议/协议版本
     URL通常都是相对服务器的根目录,因此以“/”开头。
     请求头部:请求的头部包含了关于客户端环境和请求的主体内容的有用信息。例如它可能包括浏览器设置的语言,主体内容的长度等等。每个头部通过一个回车换行符(CRLF)来分隔的。
     请求主体内容:对于HTTP请求格式来说,头部和主体内容之间有一个回车换行符(CRLF)是相当重要的。CRLF告诉HTTP服务器主体内容是在什么地方开始的。在一些互联网编程书籍中,CRLF还被认为是HTTP请求的第四部分。
3、 HTTP响应也包括三个部分: 
· 方法—统一资源标识符(URI)—协议/版本
· 响应的头部
· 主体内容
二、服务器与客户端通讯
1、服务器与客户端通讯需要用到两个部分:Socket(客户端)和ServerSocket(服务器端)
(1)ServerSocket(java.net.ServerSocket, 服务器端套接字),要创建一个服务器套接字,你需要使用ServerSocket类提供的四个构造方法中的一个。你需要指定IP地址和服务器套接字将要进行监听的端口号。通常,IP地址将会是127.0.0.1,也就是说,服务器套接字将会监听本地机器。服务器套接字正在监听的IP地址被称为是绑定地址。服务器套接字的另一个重要的属性是backlog,这是服务器套接字开始拒绝传入的请求之前,传入的连接请求的最大队列长度,四种构造方法分别为:
          ServerSocket ss = new ServerSocket();//创建一个未绑定的ServerSocket
          ServerSocket ss = new ServerSocket(int port);//创建一个绑定到某端口的ServerSocket
          ServerSocket ss = new ServerSocket(int port, int log);//创建一个绑定到某端口的ServerSocket,并设置了最大队列长度。
          ServerSocket ss = new ServerSocket(int port, int log, InetAddress address);//创建一个绑定到某地址、某端口的ServerSocket,并设置了最大队列长度。
          对于第四个构造方法,绑定地址必须是InetAddress的一个实例,一种构造InetAddress对象的简单的方法是调用它的静态方法getByName,传入一个包含主机名称的字符串,就像下面的代码一样。
               InetAddress.getByName("127.0.0.1");
      创建ServerSocket的常用方法:  
               new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"));
      代码构造了一个监听本地机器8080端口的ServletSocket,它的队列长度为1. 
      服务器创建后就保持等待状态(TCP协议,可靠的传输协议,是同步协议,即没有响应返回就一直等待)
(2)Socket(java.net.Socket类,客户端套接字):需要知道要访问的服务器端的IP/主机名和端口号,即可向服务器端发送请求。可以用Socket的众多构造方法中的一个来建立Socket         
       new Socket ("yahoo.com", 80);
     一旦你成功创建了一个Socket类的实例,你可以使用它来发送和接受字节流。要发送字节流,你首先必须调用Socket类的getOutputStream方法来获取一个java.io.OutputStream对象。要发送文本到一个远程应用,你经常要从返回的OutputStream对象中构造一个java.io.PrintWriter对象。要从连接的另一端接受字节流,你可以调用Socket类的getInputStream方法用来返回一个java.io.InputStream对象。 
(3)服务器端通过accept()方法来接收客户端的连接请求,并与客户端建立连接,同时返回一个Socket
          Socket s =  ss. accept();
(4)通过Socket可以获得一个输入流和一个输出流, 输入流用于读取客户端请求数据,输出流用于向客户端返回响应信息。
比如:InputStream input =  s.getInputStream();
          OutputStream output = s.getOutputStream();
三、简单的Web服务器通讯示例(建议拷贝到MyEclipse来看并执行)
1、服务器类
package com.socket.httpservertest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class HttpServer {
     public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";
     // shutdown command
     private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
     // the shutdown command received
     private boolean shutdown = false;
     public static void main(String[] args)
     {
           HttpServer server = new HttpServer();
           server.await();
           
     }
     public void await() {
     //   System.out.println(System.getProperty("user.dir"));
           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);
           }
           while (!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
                     Request request = new Request(input);
                     request.parse(); //从请求中读取内容
                     // create Response object
                     Response response = new Response(output);
                     response.setRequest(request);
                     response.sendStaticResource();
                     // Close the socket
                     socket.close();
                     //check if the previous URI is a shutdown command
                     shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
                }catch (Exception e)
                {
                     e.printStackTrace ();
                     continue;
                }
           }
    }
}
 
2、请求类
package com.socket.httpservertest;
import java.io.IOException;
import java.io.InputStream;
public class Request {
     private InputStream input;
     private String uri;
     public Request(InputStream input)
     {
           this.input = input;
     }
     
     public void parse() {
           // Read a set of characters from the socket
           StringBuffer request = new StringBuffer(2048);
           int i;
           byte[] buffer = new byte[2048];
           try {
                i = input.read(buffer); //将从输入流取2048长度的内容存到buffer字节数组中,如果内容不到2048,数组其他空间剩余空着
           } 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(' ');
           /*
            * http请求行的结构:方法 统一资源标识符(URI) 协议/版本(它们之间以空格分隔)
            * 例如:POST //examples/default.jsp HTTP/1.1
            */
           if (index1 != -1) {// index1 == -1表示没找到
                     index2 = requestString.indexOf(' ', index1 + 1);//从index+1位置开始寻找‘ ’
                     if (index2 > index1)
                     return requestString.substring(index1 + 1, index2);
                }
           return null;
     }
     
     public String getUri()
     {
           return uri;
     }
}
 
3、响应类
package com.socket.httpservertest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Response {
     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) { //ch==-1表示读到末尾了
                           output.write(bytes, 0, ch); //写出到浏览器
                           ch = fis.read(bytes, 0, BUFFER_SIZE);//再读会接上一次读的位置往下读,如果读到末尾就会返回-1,终止输出
                     }
                } else {
                     // file not found
                     String 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 object
                System.out.println(e.toString() );
           } finally {
                if (fis!=null)
                     fis.close();
           }
     }
}
 
4、示例代码功能描述:浏览器输入http请求,比如http://localhost:8080/MyHtml.html;服务器接收请求后用输入流读取请求内容获得文件位置,再用文件输入流读取文件中的内容;最后给浏览器客户端返回响应,把html文件中的内容显示在浏览器上,如图:
 

 
5、示例代码跨职能流程图:

 
 

Tomcat学习笔记(一)一个简单的Web服务器的更多相关文章

  1. 《深度解析Tomcat》 第一章 一个简单的Web服务器

    本章介绍Java Web服务器是如何运行的.从中可以知道Tomcat是如何工作的. 基于Java的Web服务器会使用java.net.Socket类和java.net.ServerSocket类这两个 ...

  2. how tomcat works 读书笔记(一)----------一个简单的web服务器

    http协议 若是两个人能正常的说话交流,那么他们间必定有一套统一的语言规则<在网络上服务器与客户端能交流也依赖与一套规则,它就是我们说的http规则(超文本传输协议Hypertext tran ...

  3. Tomcat剖析(一):一个简单的Web服务器

    Tomcat剖析(一):一个简单的Web服务器 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三):连接器 ...

  4. 自己模拟的一个简单的web服务器

    首先我为大家推荐一本书:How Tomcat Works.这本书讲的很详细的,虽然实际开发中我们并不会自己去写一个tomcat,但是对于了解Tomcat是如何工作的还是很有必要的. Servlet容器 ...

  5. 一个简单的Web服务器-支持Servlet请求

    上接 一个简单的Web服务器-支持静态资源请求,这个服务器可以处理静态资源的请求,那么如何处理Servlet请求的呢? 判断是否是Servlet请求 首先Web服务器需要判断当前请求是否是Servle ...

  6. 一个简单的Web服务器-支持静态资源请求

    目标 实现一个简单的Web服务器,能够根据HTTP请求的URL响应对应的静态资源,如果静态资源不存在则响应404. HttpServer 使用ServerSocket实现的一个服务器,request根 ...

  7. 自己动手模拟开发一个简单的Web服务器

    开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此事要躬行”,于是我们自己模拟一个简单的W ...

  8. 一个简单的web服务器

    写在前面 新的一年了,新的开始,打算重新看一遍asp.net本质论这本书,再重新认识一下,查漏补缺,认认真真的过一遍. 一个简单的web服务器 首先需要引入命名空间: System.Net,关于网络编 ...

  9. [置顶] 在Ubuntu下实现一个简单的Web服务器

    要求: 实现一个简单的Web服务器,当服务器启动时要读取配置文件的路径.如果浏览器请求的文件是可执行的则称为CGI程序,服务器并不是将这个文件发给浏览器,而是在服务器端执行这个程序,将它的标准输出发给 ...

  10. 利用 nodeJS 搭建一个简单的Web服务器(转)

    下面的代码演示如何利用 nodeJS 搭建一个简单的Web服务器: 1. 文件 WebServer.js: //-------------------------------------------- ...

随机推荐

  1. Angular环境准备和Angular cli

    Angular4.0来了,更小,更快,改动少 接下来为Angular4.0准备环境和学会使用Angular cli项目 1.环境准备: 1)在开始工作之前我们必须设置好开发环境 如果你的机器上还没有安 ...

  2. 基于OWIN+DotNetOpenOAuth实现OAuth2.0

    这几天时间一直在研究怎么实现自己的OAuth2服务器,对于太了解OAuth原理以及想自己从零开始实现的,我建议可以参考<Apress.Pro ASP.NET Web API Security&g ...

  3. 谷歌发布基于机器学习的Android APP安全检测系统:Google Play Protect

    Google Play作为众所周知的在线应用市场,因为审查制度的松散,经常会有一些恶意软件伪装成其他应用混入其中.此前阿里聚安全小编就报道了2例关于恶意软件伪装在Google Play上的事件:< ...

  4. Linux Set Command

    1. set -e "Exit immediately if a simple command exits with a non-zero status." When this o ...

  5. stm32之IIC通信协议

    I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备. 它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数 ...

  6. Venn Diagram Comparison of Boruta, FSelectorRcpp and GLMnet Algorithms

    Feature selection is a process of extracting valuable features that have significant influence ondep ...

  7. javascript获取json对象的key名称的两种方法

    javascript获取json对象的key名称的两种方法 数据处理中,你可能接收到一个不确定内容格式的json对象,然后要把key的值提取出来.今天试过两种可以提取json key的方法,均可以正常 ...

  8. Swoole笔记(一)

    简介 Swoole是一个PHP扩展,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连接池,AsyncTask,消息队列,毫秒定时器,异步文件读 ...

  9. Qt之添加图标

    导读: 在使用Qt Creator编写完应用程序后,设置release版的应用程序图标着实困扰了不少的人.一个漂亮的图标是一个软件的脸,没有一个漂亮的图标,那么这个程序是不完整的.那么我们来看看如何设 ...

  10. Java常用类之【日期相关类】

    一.日期类 Java语言提供了2个类来处理日期 Date类 Date类以毫秒来表示特定的日期 构造方法 Date date = new Date(); System.out.println(date) ...