JavaSE02_Day04(中)-WebServer项目(五、六:重构项目、显示图片)

1.1 版本五:重构项目

  将ClientHandler类中响应客户端的操作进行重构,设计一个类HttpResponse类,用它的每一个实例表示服务端发送给客户端的一个具体的响应内容:

  1. 在http包下添加类:HttpResponse.java

  1. 在HttpResponse类中定义方法flush,用来将当前响应发送给客户端。flush方法需要处理的三件事情:

    2.1 发送状态行

    2.2 发送响应头

    2.3 发送响应正文

  1. 将ClientHandler类中响应客户端的操作移动到HttpResponse类中的对应方法中.

  1. 在ClientHandler类中实例化HttpResponse,并设置要响应的内容后调用flush方法响应客户端

新建HttpResponse.java响应客户端请求类

 package cn.tedu.http;
 /**
  * 向客户端进行响应
  * @author cjn
  *
  */
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.Socket;
 
 public class HttpResponse {
     /**
       * 有关于状态行相关信息定义
      */
     private int statusCode = 200;
     private String statusReason = "OK";
     
     /**
       * 有关于响应头相关信息定义
      */
     
     /**
      * 有关于响应正文相关信息定义
      */
     private File entity;
     
     /**
       * 相关连接信息定义
      */
     private Socket socket;
     private OutputStream out;
     
     /**
      * 构造器方法,完成相关连接信息属性的赋值
      */
     public HttpResponse(Socket socket) {
         try {
             this.socket = socket;
             this.out = socket.getOutputStream();
        } catch (Exception e) {
             e.printStackTrace();
        }
    }
     
     /**
       * 调用发送响应信息的三个方法,完成响应客户端信息的操作
      */
     public void flush() {
         /*
           * 响应客户端
          * 1.发送状态行
          * 2.发送响应头
          * 3.发送响应正文
          */
         sendStatusLine();
         sendHeader();
         sendContext();
    }
     
     /**
      * 发送状态行
      */
     public void sendStatusLine() {
         try {
             String line = "HTTP/1.1 "+statusCode+" "+statusReason;
             out.write(line.getBytes("ISO8859-1"));
             out.write(13);//CR
             out.write(10);//LF
        } catch (UnsupportedEncodingException e) {
             e.printStackTrace();
        } catch (IOException e) {
             e.printStackTrace();
        } catch (Exception e) {
             e.printStackTrace();
        }
    }
     
     /**
       * 发送响应头
      */
     public void sendHeader() {
         try {
             //通过输出流对象发送响应头,响应对应的媒介类型资源
             String line = "Content-Type: text/html";//媒介类型
             out.write(line.getBytes("ISO8859-1"));
             out.write(13);//CR
             out.write(10);//LF
             
             line = "Content-Length: " + entity.length();
             out.write(line.getBytes("ISO8859-1"));
             out.write(13);//CR
             out.write(10);//LF
             //当响应头写出完毕以后末尾还需要写出一个CRLF
             out.write(13);//CR
             out.write(10);//LF  
        } catch (UnsupportedEncodingException e) {
             e.printStackTrace();
        } catch (IOException e) {
             e.printStackTrace();
        } catch (Exception e) {
             e.printStackTrace();
        }
    }
     
     /**
       * 发送响应正文
      */
     public void sendContext() {
         /*
           * 通过输出流对象发送响应正文
           * 注意:不能使用上面的out对象进行发送响应正文(index.html),
           * 因为这个输出流对象是通过连接客户端获取的socket对象得到的输出流对象,
           * 当前发送响应正文,实际是需要将服务端中的index.html页面资源发送给客户端,
           * 需要使用到服务端自己的输出流对象进行写出数据,也就是Java内部获取输出流对象,
           * 将服务器内部的资源进行写出。
           * 1.先将服务器端的文件资源读取到内存中
           * 2.然后再使用输出流对象进行写出操作
          */
         try (//在try块中关闭流资源
        FileInputStream fis = new FileInputStream(entity);
        //此处如果报错,提示需要JDK5以上版本,需要对项目将进行设置(项目上右键---Properties---Project Facets---Java---选择1.8版本)
      ){  
             byte[] data = new byte[1024 * 10];
             int len = -1;
             while ((len = fis.read(data)) != -1) {
                 out.write(data, 0, len);
            }
        } catch (FileNotFoundException e) {
             e.printStackTrace();
        } catch (IOException e) {
             e.printStackTrace();
        } catch (Exception e) {
             e.printStackTrace();
        }
         
    }
     
     /**
       * 添加属性的set和get方法
      */
     public int getStatusCode() {
         return statusCode;
    }
     public void setStatusCode(int statusCode) {
         this.statusCode = statusCode;
    }
     public String getStatusReason() {
         return statusReason;
    }
     public void setStatusReason(String statusReason) {
         this.statusReason = statusReason;
    }
     public File getEntity() {
         return entity;
    }
     public void setEntity(File entity) {
         this.entity = entity;
    }
   
 }

ClientHandler.java类修改

 package cn.tedu.core;
 /**
  * 处理客户端请求的任务序列类
  * @author cjn
  *
  */
 
 import java.io.File;
 import java.net.Socket;
 import cn.tedu.http.HttpRequest;
 import cn.tedu.http.HttpResponse;
 
 public class ClientHandler implements Runnable{
     //声明获取连接客户端以后,获取的socket对象
     private Socket socket;
     
     /**
      * 构造方法,进行初始化操作
      */
     public ClientHandler(Socket socket) {
         this.socket = socket;
    }
     
     /**
      * 线程所执行的任务序列逻辑
      */
     public void run() {
         
         try {
             //创建HttpRequest对象
             HttpRequest request = new HttpRequest(socket);
             
             //创建HttpResponse响应对象
             HttpResponse response = new HttpResponse(socket);
             
             //测试解析请求的相关内容
             System.out.println(request.getUrl());
             System.out.println(request.getHeaders("Accept"));
             
             /*
              * 对用户的请求进行响应:
              * 1.需要获取用户请求的资源路径
              * 2.根据用户请求的资源,在当前项目中进行查找并响应资源
              */
             String requestUrl = request.getUrl();
             //webapps/myweb/index.html
             File file = new File("webapps" + requestUrl);
             //判断是否可以找到index.html首页资源
             if (file.exists()) {
                 System.out.println("找到资源页面");
                 //找到首页资源
                 //设置文件资源
                 response.setEntity(file);
                                         
            } else {
                 System.out.println("未找到资源页面");
                 //未找到资源响应404页面
                 File notFoundFile = new File("webapps/root/404.html");
                 response.setStatusCode(404);
                 response.setStatusReason("Not Found");
                 response.setEntity(notFoundFile);
            }
             
             //调用发送响应的flush方法
             response.flush();
             System.out.println("响应结束!!!");
        } catch (Exception e) {
             e.printStackTrace();
        }
         
    }
 }

测试:

(1)启动WebServer主类,然后打开浏览器,在浏览器的地址栏中输入http://localhost:8888/myweb/index.html访问首页资源的路径,查看浏览器页面上是否显示自定义首页。

  输出结果:

 正在启动服务器端......
 服务器端已经启动成功!
 正在等待客户端连接......
 一个客户端已经连接完毕!
 正在等待客户端连接......
 一个客户端已经连接完毕!
 正在等待客户端连接......
 HttpRequest开始解析请求......
 开始解析请求行......
 请求行:GET /myweb/index.html HTTP/1.1
 HttpRequest开始解析请求......
 开始解析请求行......
 method:GET
 url:/myweb/index.html
 protocal:HTTP/1.1
 解析请求行完毕!
 开始解析消息头......
 Host: localhost:8888
 Connection: keep-alive
 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
 sec-ch-ua-mobile: ?0
 Upgrade-Insecure-Requests: 1
 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Sec-Fetch-Site: none
 Sec-Fetch-Mode: navigate
 Sec-Fetch-User: ?1
 Sec-Fetch-Dest: document
 Accept-Encoding: gzip, deflate, br
 Accept-Language: zh-CN,zh;q=0.9
 解析消息头完毕!
 开始解析消息正文......
 解析消息正文完毕!
 HttpRequest解析请求完毕!
 /myweb/index.html
 keep-alive
 找到资源页面
 响应结束!!!

(2)在浏览器的地址栏中输入http://localhost:8888/myweb/qwer.html,查看当前在浏览器页面上是否显示404自定找不到资源页面。

输出结果

 正在启动服务器端......
 服务器端已经启动成功!
 正在等待客户端连接......
 一个客户端已经连接完毕!
 正在等待客户端连接......
 一个客户端已经连接完毕!
 正在等待客户端连接......
 HttpRequest开始解析请求......
 HttpRequest开始解析请求......
 开始解析请求行......
 开始解析请求行......
 请求行:GET /myweb/index1.html HTTP/1.1
 method:GET
 url:/myweb/index1.html
 protocal:HTTP/1.1
 解析请求行完毕!
 开始解析消息头......
 Host: localhost:8888
 Connection: keep-alive
 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
 sec-ch-ua-mobile: ?0
 Upgrade-Insecure-Requests: 1
 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Sec-Fetch-Site: none
 Sec-Fetch-Mode: navigate
 Sec-Fetch-User: ?1
 Sec-Fetch-Dest: document
 Accept-Encoding: gzip, deflate, br
 Accept-Language: zh-CN,zh;q=0.9
 解析消息头完毕!
 开始解析消息正文......
 解析消息正文完毕!
 HttpRequest解析请求完毕!
 /myweb/index1.html
 keep-alive
 未找到资源页面
 响应结束!!!

附:修改项目JDK版本

1.2 版本六:导入图片

  在index.html页面中显示一张图片,当我们导入图片的时候发现,请求的页面无法显示图片,原因是Content-Type指明客户端请求的资源实际类型是固定的text/html,导致在显示页面的时候图片无法显示。

  1. 在WebServer主类中的start()方法中添加while循环,确保当页面包含其他资源时(图片,音频等),浏览器在解析该页面时自动再次发起请求向服务器索取这些资源,并将内容可以显示到浏览器上时还可以有线程分配。

  2. 修改响应头,使得响应时的响应头变成可以随机的,灵活的进行设置,这样才可以根据实际情况,响应不同的内容

    2.1 在HttpResponse类中定义一个属性Map:headers,其中,key保存响应头的名字,value保存对应的值

    2.2 对外提供一个putHeaders方法,用于往Map中添加元素

    2.3 修改sendHeaders方法,将原有的代码改变为可以根据headers中实际保存的响应头来进行发送

 package cn.tedu.http;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.Socket;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 
 /**
  * 向客户端进行响应
  * @author cjn
  *
  */
 public class HttpResponse {
  /**
  * 有关于状态行相关信息定义
  */
  private int statusCode = 200;
  private String statusReason = "OK";
 
  /**
  * 有关于响应头相关信息定义
  * 用于存储响应的媒介类型
  */
  private Map<String,String> headers = new HashMap<String,String>();
 
  /**
  * 有关于响应正文相关信息定义
  */
  private File entity;
 
  /**
  * 相关连接信息定义
  */
  private Socket socket;
  private OutputStream out;
 
  /**
  * 构造器方法,完成相关连接属性的赋值
  */
  public HttpResponse(Socket socket){
  try {
  this.socket = socket;
  this.out = socket.getOutputStream();
  } catch (IOException e) {
  e.printStackTrace();
  } catch (Exception e) {
  e.printStackTrace();
  }
  }
 
  /**
  * 调用发送响应信息的三个方法,完成响应客户端信息的操作
  */
  public void flush(){
  /**
  * 响应客户端
  * 1.发送状态行
  * 2.发送响应头
  * 3.发送响应正文
  */
  sendStatusLine();
  sendHeader();
  sendContext();
  }
 
  /**
  * 发送状态行
  */
  public void sendStatusLine(){
  try {
  String line = "HTTP/1.1 " + statusCode + " " + statusReason;
  out.write(line.getBytes("ISO8859-1"));
  out.write(13);//CR
  out.write(10);//LF
  } catch (UnsupportedEncodingException e) {
  e.printStackTrace();
  } catch (IOException e) {
  e.printStackTrace();
  } catch (Exception e) {
  e.printStackTrace();
  }
  }
 
  /**
  * 发送响应头
  */
  public void sendHeader(){
  try {
  //通过输出流对象发送响应头,响应对应媒介类型资源
 // String line = "Content-Type: text/html";
 // out.write(line.getBytes("ISO8859-1"));
 // out.write(13);
 // out.write(10);
 //
 // line = "Content-Length: " + entity.length();
 // out.write(line.getBytes("ISO8859-1"));
 // out.write(13);
 // out.write(10);
 // //当响应头写出完毕后,末尾还需要写出一个CRLF
 // out.write(13);
 // out.write(10);
  //以键值对的形式遍历headers
  for (Entry<String,String> entry: headers.entrySet()) {
  //取出Map中的key和value
  String key = entry.getKey();
  String value = entry.getValue(); 
          String line = key + ": " + value; 
          System.out.println("发送的响应头为:" + line); 
          out.write(line.getBytes("ISO8859-1")); 
          out.write(13); 
          out.write(10); 
      } 
        //末尾还需要单独发送一个CRLF 
        out.write(13); 
        out.write(10); 
    } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
  } catch (IOException e) { 
      e.printStackTrace(); 
  } catch (Exception e) { 
      e.printStackTrace(); 
  } 

 
  /** 
  * 发送响应正文 
  */ 
  public void sendContext(){ 
  /* 
        * 通过输出流对象发送响应正文 
        * 注意:不能使用上面的out对象进行发送响应正文(index.html), 
        * 因为这个输出流对象是通过连接客户端获取的socket对象得到的输出流对象, 
        * 当前发送响应正文,实际是需要将服务端中的index.html页面资源发送给客户端, 
        * 需要使用到服务端自己的输出流对象进行写出数据,也就是Java内部获取输出流对象, 
        * 将服务器内部的资源进行写出。 
        * 1.先将服务器端的文件资源读取到内存中 
        * 2.然后再使用输出流对象进行写出操作 
       */ 
    try( 
      FileInputStream fis = new FileInputStream(entity);  
    ) { 
      byte[] data = new byte[1024*10]; 
      int len = -1; 
      while((len=fis.read(data))!=-1){ 
      out.write(data,0,len); 
  } 
  } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
  } catch (Exception e) { 
      e.printStackTrace(); 
  }  
 } 
​ 
  /** 
  * 添加属性的set和get方法 
  */ 
  public int getStatusCode() { 
    return statusCode; 
  } 
​ 
  public void setStatusCode(int statusCode) { 
    this.statusCode = statusCode; 
  } 
​ 
  public String getStatusReason() { 
    return statusReason; 
  } 
​ 
  public void setStatusReason(String statusReason) { 
    this.statusReason = statusReason; 
  } 
​ 
  public File getEntity() { 
    return entity; 
  } 
​ 
  public void setEntity(File entity) { 
    this.entity = entity; 

 
  /** 
  * 对外提供可以向响应头的Map进行赋值的方法 
  * @param key 
  * @param value 
  */ 
  public void putHeaders(String key,String value){ 
    this.headers.put(key, value); 
  } 

3. 在ClientHandler类中获取请求路径,根据请求路径后缀,判断请求的是网页还是图片,然后进行修改响应头

 package cn.tedu.core;
 /**
  * 处理客户端请求的任务序列类
  * @author cjn
  *
  */
 
 import java.io.File;
 import java.net.Socket;
 import java.util.HashMap;
 import java.util.Map;
 
 import cn.tedu.http.HttpRequest;
 import cn.tedu.http.HttpResponse;
 
 public class ClientHandler implements Runnable{
     //声明获取连接客户端以后,获取的socket对象
     private Socket socket;
     
     public ClientHandler(Socket socket) {
         this.socket = socket;
    }
     
     /**
      * 线程所执行的任务序列逻辑
      */
     public void run() {
         
         try {
             //创建HttpRequest对象
             HttpRequest request = new HttpRequest(socket);
             
             //创建HttpResponse响应对象
             HttpResponse response = new HttpResponse(socket);
             
             //测试解析请求的相关内容
             System.out.println(request.getUrl());
             System.out.println(request.getHeaders("Accept"));
             
             /*
               * 对用户的请求进行响应:
              * 1.需要获取用户请求的资源路径
              * 2.根据用户请求的资源,在当前项目中进行查找并响应资源
              */
             String requestUrl = request.getUrl();
             //webapps/myweb/index.html
             //webapps/myweb/google.png
             File file = new File("webapps" + requestUrl);
             //判断是否可以找到index.html首页资源
             if (file.exists()) {
                 System.out.println("找到资源页面");
                 //找到首页资源
                 //设置文件资源
                 response.setEntity(file);
                 //获取请求资源的后缀名
                 String fileName = file.getName();
                 int index = fileName.lastIndexOf(".");
                 String suffix = fileName.substring(index + 1);
                 
                 /*
                   * 定义一个Map对象,这个Map中需要添加多个媒介类型作为Map的value值,
                   * 而key可以根据需要进行请求的资源后缀作为key值,这个Map的主要作用
                   * 是用于根据用户的请求不同,进行查询出不同的媒介类型
                  */
                 Map<String, String> map = new HashMap<String, String>();
                 map.put("html", "text/html");
                 map.put("png", "image/png");
                 map.put("jpg", "image/jpeg");
                 //查询请求的资源,需要使用什么媒介类型
                 String mime = map.get(suffix);
                 
                 //向HttpResponse对象中的headers进行赋值,目的是后期进行发送响应头
                 response.putHeaders("Content-Type", mime);
                 response.putHeaders("Content-Length", file.length()+"");
                                         
            } else {
                 System.out.println("未找到资源页面");
                 //未找到资源响应404页面
                 File notFoundFile = new File("webapps/root/404.html");
                 response.setStatusCode(404);
                 response.setStatusReason("Not Found");
                 response.setEntity(notFoundFile);
 
                 response.putHeaders("Content-Type", "text/html");
                 response.putHeaders("Content-Length", notFoundFile.length()+"");    
            }
             //调用发送响应的flush方法
             response.flush();
             System.out.println("响应结束!!!");
        } catch (Exception e) {
             e.printStackTrace();
        } finally{
        try{
          socket.close();
        } catch(){
          e.printStackTrace();
        } catch(){
          e.printStackTrace();
        }
      }
    }
 }

输出结果:

(1)访问存在资源,有时候存在空请求现象,图片有时候加载不出来或者加载失败

 正在启动服务器端......
 服务器端已经启动成功!
 正在等待客户端连接......
 一个客户端已经连接完毕!
 正在等待客户端连接......
 一个客户端已经连接完毕!
 正在等待客户端连接......
 HttpRequest开始解析请求......
 开始解析请求行......
 HttpRequest开始解析请求......
 开始解析请求行......
 请求行:GET /myweb/index.html HTTP/1.1
 method:GET
 url:/myweb/index.html
 protocal:HTTP/1.1
 解析请求行完毕!
 开始解析消息头......
 Host: localhost:8888
 Connection: keep-alive
 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
 sec-ch-ua-mobile: ?0
 Upgrade-Insecure-Requests: 1
 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Sec-Fetch-Site: none
 Sec-Fetch-Mode: navigate
 Sec-Fetch-User: ?1
 Sec-Fetch-Dest: document
 Accept-Encoding: gzip, deflate, br
 Accept-Language: zh-CN,zh;q=0.9
 解析消息头完毕!
 开始解析消息正文......
 解析消息正文完毕!
 HttpRequest解析请求完毕!
 /myweb/index.html
 keep-alive
 找到资源页面
 发送的响应头为:Content-Length: 351
 发送的响应头为:Content-Type: text/html
 响应结束!!!
 请求行:GET /myweb/google.png HTTP/1.1
 method:GET
 url:/myweb/google.png
 protocal:HTTP/1.1
 解析请求行完毕!
 开始解析消息头......
 Host: localhost:8888
 Connection: keep-alive
 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
 sec-ch-ua-mobile: ?0
 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
 Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
 Sec-Fetch-Site: same-origin
 Sec-Fetch-Mode: no-cors
 Sec-Fetch-Dest: image
 Referer: http://localhost:8888/myweb/index.html
 Accept-Encoding: gzip, deflate, br
 Accept-Language: zh-CN,zh;q=0.9
 解析消息头完毕!
 开始解析消息正文......
 解析消息正文完毕!
 HttpRequest解析请求完毕!
 /myweb/google.png
 keep-alive
 找到资源页面
 发送的响应头为:Content-Length: 10232
 发送的响应头为:Content-Type: image/png
 响应结束!!!

显示效果:

(2)访问不存在的资源,存在空请求现象,图片有时候加载不出来或者加载失败

 正在启动服务器端......
 服务器端已经启动成功!
 正在等待客户端连接......
 一个客户端已经连接完毕!
 正在等待客户端连接......
 一个客户端已经连接完毕!
 正在等待客户端连接......
 HttpRequest开始解析请求......
 开始解析请求行......
 HttpRequest开始解析请求......
 开始解析请求行......
 请求行:GET /myweb/index1.html HTTP/1.1
 method:GET
 url:/myweb/index1.html
 protocal:HTTP/1.1
 解析请求行完毕!
 开始解析消息头......
 Host: localhost:8888
 Connection: keep-alive
 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
 sec-ch-ua-mobile: ?0
 Upgrade-Insecure-Requests: 1
 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Sec-Fetch-Site: none
 Sec-Fetch-Mode: navigate
 Sec-Fetch-User: ?1
 Sec-Fetch-Dest: document
 Accept-Encoding: gzip, deflate, br
 Accept-Language: zh-CN,zh;q=0.9
 解析消息头完毕!
 开始解析消息正文......
 解析消息正文完毕!
 HttpRequest解析请求完毕!
 /myweb/index1.html
 keep-alive
 未找到资源页面
 发送的响应头为:Content-Length: 266
 发送的响应头为:Content-Type: text/html
 响应结束!!!
 请求行:GET /myweb/404.jpg HTTP/1.1
 method:GET
 url:/myweb/404.jpg
 protocal:HTTP/1.1
 解析请求行完毕!
 开始解析消息头......
 Host: localhost:8888
 Connection: keep-alive
 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
 sec-ch-ua-mobile: ?0
 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
 Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
 Sec-Fetch-Site: same-origin
 Sec-Fetch-Mode: no-cors
 Sec-Fetch-Dest: image
 Referer: http://localhost:8888/myweb/index1.html
 Accept-Encoding: gzip, deflate, br
 Accept-Language: zh-CN,zh;q=0.9
 解析消息头完毕!
 开始解析消息正文......
 解析消息正文完毕!
 HttpRequest解析请求完毕!
 /myweb/404.jpg
 keep-alive
 找到资源页面
 发送的响应头为:Content-Length: 51514
 发送的响应头为:Content-Type: image/jpeg
 响应结束!!!

显示结果:

 

posted @ 2021-07-15 23:13  Coder_Cui  阅读(51)  评论(0编辑  收藏  举报