码迷,mamicode.com
首页 > Web开发 > 详细

一个简单的Web服务器

时间:2018-04-21 15:23:43      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:构造函数   resource   text   3.3   exist   iat   端口   远程   set   

一个简单的Web服务器

  • Web服务器也称为超文本传输协议(HyperText Transfer Protocol)服务器,因为它使用HTTP和客户端(通常是Web浏览器)进行通信
  • 基于JavaWeb服务器会使用到两个重要的类:java.net.Socket类和java.net.ServerSocket类,并通过发送HTTP消息进行通信。

    1.1 HTTP

  • HTTP允许Web服务器和浏览器通过Internet发送并接受数据,是一种基于“请求--响应”的协议。
  • HTTP使用可靠地TCP连接,TCP协议默认使用TCP 80端口。
  • HTTP中总是有客户端通过建立连接并发送HTTP请求来初始化一个事务的。客户端或服务器可提前关闭连接
  • 1.1.1 HTTP请求
    • HTTP请求包含三部分:
      1. 请求方法--统一资源标识符URI--协议/版本
      2. 请求头
      3. 实体
    • 每个HTTP请求可以使用HTTP标准中指定方法中的一种。HTTP1.1支持的方法:GET,POST,HEAD,OPTIONS,PUT,DELETE,TRACE
    • URI 指定Internet资源的完整路径。URI通常为服务器根目录的相对路径
    • 请求头包含客户端环境和请求实体之间的相关信息
    • 请求头和实体之间包含一个空行,该空行只有CRLF字符,CRLF告诉HTTP服务器请求实体正文从哪里开始
  • 1.1.2 HTTP响应
    • HTTP响应包含三部分:
      • 协议--状态码--描述
      • 响应头
      • 响应实体
  • 1.2 Socket类

  • 套接字是网络连接的断电。套接字使应用程序可以从网络中读写数据。
  • 应用程序之间发送或接收消息,需要知道另一个应用程序中套接字的IP地址和端口号。Java中套接字由java.net.Socket表示
  • 创建一个套接字:
    • public Socket(java.net.String host,int port)
  • 创建成功Socket实例,就可以使用该实例发送或接受字节流。要发送字节流需要调用Socket类的getOutputStream方法获取一个OutputStream对象。接收字节流使用getInputStream方法获得输入流InputStream对象
  • ServerSocket类
  • Socket表示客户端套接字,即想要连接到远程服务器应用程序时创建的套接字。
  • 如果要实现一个服务器向客户端发送响应,则需要另一种套接字ServerSocket。因为服务器需要时刻待命,等待客户端发起连接。
  • ServerSocket类和Socket类并不相同。服务器套接字需要等待来自客户端的连接。当服务器套接字收到了连接请求后,会创建一个Socket实例处理与客户端的通信。
  • 要创建服务器套接字,可以使用ServerSocket类提供的4个构造函数中的任意一个:需要指明IP地址和服务器套接字侦听的端口号。
    • //如果主机只有一个IP 地址, 那么默认情况下, 服务器程序就与该IP 地址绑定. ServerSocket 的第 4 个构造方法 ServerSocket(int port, int backlog, InetAddress bingAddr) 有一个 bindAddr 参数, 它显式指定服务器要绑定的IP 地址, 该构造方法适用于具有多个IP 地址的主机. 假定一个主机有两个网卡, 一个网卡用于连接到 Internet, IP为 222.67.5.94, 还有一个网卡用于连接到本地局域网, IP 地址为 192.168.3.4. 如果服务器仅仅被本地局域网中的客户访问, 那么可以按如下方式创建 ServerSocket:
      ServerSocket serverSocket = new ServerSocket(8000, 10, InetAddress.getByName("192.168.3.4"));

      1.3应用程序

  • Web服务器应用程序包含三个类:
    • HTTPServer
    • Request
    • Response
    • 应用程序入口点(静态main方法)在HTTPServer类中,main方法创建一个HTTPServer实例,然后调用其await方法。该方法会在指定端口上等待HTTP请求,对其进行处理,然后发送响应信息会客户端。
  • 1.3.1 HTTPServer类
    • ```java
      package ex01.pyrmont;

      import java.net.Socket;
      import java.net.ServerSocket;
      import java.net.InetAddress;
      import java.io.InputStream;
      import java.io.OutputStream;
      import java.io.IOException;
      import java.io.File;

      public class HttpServer {

      /** 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 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() {
          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 request
          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;
              }
          }
      }
      }
  • 1.3.2 Request类
  • Request类表示一个HTTP请求。可以传递InputStream对象,来创建Request对象。使用read方法读取HTTP中的数据:
    • ```java
      package ex01.pyrmont;

      import java.io.InputStream;
      import java.io.IOException;

      public class Request {

      private InputStream input;
      private String uri;
      
      public Request(InputStream input) {
          this.input = input;
      }
      
      public void parse() {//解析HTTP请求中原始数据
          // 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);
          }
          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;
      }

      }

      1.3.3 Response类

  •     package ex01.pyrmont;
        import java.io.OutputStream;
        import java.io.IOException;
        import java.io.FileInputStream;
        import java.io.File;
    
        /*
        HTTP Response = Status-Line
            *(( general-header | response-header | entity-header ) CRLF)
            CRLF
            [ message-body ]
            Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
        */
    
        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) {
                    output.write(bytes, 0, ch);
                    ch = fis.read(bytes, 0, BUFFER_SIZE);
                    }
                }
                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();
                }
            }
        }

    运行结果
    技术分享图片

一个简单的Web服务器

标签:构造函数   resource   text   3.3   exist   iat   端口   远程   set   

原文地址:https://www.cnblogs.com/Black-Cobra/p/8901051.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!