入门Java编程的知识点—>Http协议(day20)

news2024/11/15 10:39:20
  • 了解http协议是什么
  • 掌握http请求信息、响应信息格式
项目目标:

实现本地客户端与服务器一问一答的请求与响应,了解http协议即可.

项目步骤:
  1. 服务器端代码编写
    • 先在当前src文件下新建一个包: webserver,再该包下创建一个类Server,书写代码如下:

      package webserver;
      import java.io.IOException;
      import java.net.ServerSocket;
      import java.net.Socket;
      /**
       * 服务端的使用演示类:
       */
      
      public class Server {
          ServerSocket serverSocket;
          Server() {
              try {
                  serverSocket = new ServerSocket(8088);//创建服务器 并设置端口
      
             } catch (IOException e) {
                  e.printStackTrace();
             }
         }
          public static void main(String[] args) {
              Server s = new Server();
         }
      }
      
    • 运行测试以下状态:

      • 弹出下列窗口直接点击允许访问即可.

      • 控制台中如果报错如下:

      • 运行成功:

    • 再当前WebServer类中添加start方法,主要编写接收客户端请求代码

    package webserver;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    /**
    
     * 服务端的使用演示类:
    
     */
    
    public class Server {
        ServerSocket serverSocket;
        Server() {
            try {
                serverSocket = new ServerSocket(8088);//创建服务器 并设置端口
    
           } catch (IOException e) {
                e.printStackTrace();
           }
       }
        public void start() {
            try {
                System.out.println("等待客户端链接");
                Socket socket = serverSocket.accept();
                System.out.println("客户端已链接");
                ClientHandle handle = new ClientHandle(socket);//将socket对象 传递给构
    造方法中
    
                handle.run();//执行解析请求和响应的方法
    
           } catch (IOException e) {
                e.printStackTrace();
           }
       }
        public static void main(String[] args) {
            Server s = new Server();
            s.start();//调用start方法
       }
    }
    
    • 运行测试:

      • 当控制台中显示如下:

      • 打开浏览器,在地址栏中输入localhost:8088 回车即可

      • 打开控制台查看是否显示一个客户端已连接,显示则表示客户端已经连接服务器并给服务器发送请求

  2. 处理客户端发送的请求并响应
    • 在当前项目包下新建一个类:ClientHandler

      package webserverdemo;
      
      import java.net.Socket;
      
      /**
       * 处理客户端发送的请求   --处理请求并响应
       */
      public class ClientHandler {
          private Socket socket;
          public ClientHandler(Socket socket){
              this.socket = socket;
          }
      	/** 自定义一个run方法,用来处理和响应客户端发送来的请求
      	*
      	*/
          public void run() { 
      		
          }
      }
    • 在WebServer类中的start方法,实例化ClientHandler对象并将接收到的socket对象传递构造方法进行赋值.

    • 那么目前我们已经清楚了客户端是如何连接服务端,以及也看到了连接后客户端发送的请求信息,现在我们来认识一下HTTP协议

HTTP协议(面试重点)
HTTP概念
  • HTTP协议 超文本传输协议 由万维网制定(w3c)

    是浏览器与服务器通讯的应用层协议,规定了浏览器与服务器之间的交互规则以及交互数据的格式信息等。

  • TCP协议 工作在传输层,主要关注的是,客户端与服务器建立连接,互相传递数据的协议

HTTP交互规则

HTTP协议对于客户端与服务端之间的交互规则有以下定义:

  1. 要求浏览器与服务端之间必须遵循一问一答的规则,即:浏览器与服务端建立TCP连接后需要 先发送一个请求(问),然后服务端接收到请求并予以处理后再发送响应(答)。注意,服务端永远 不会主动给浏览器发送信息。

  2. HTTP要求浏览器与服务端的传输层协议必须是可靠的传输,因此是使用TCP协议作为传输层 协议的。

HTTP请求和响应(必须记住)
  • HTTP协议对于浏览器与服务端之间交互的数据格式,内容也有一定的要求。

    • 浏览器给服务端发送的内容称为请求Request
    • 服务端给浏览器发送的内容称为响应Response
  • 请求和响应中大部分内容都是文本信息(字符串),并且这些文本数据使用的字符集为: ISO8859-1.这是一个欧洲的字符集,里面是不支持中文的!!!。而实际上请求和响应出现 的字符也就是英文数字符号

请求Request

请求是浏览器发送给服务端的内容,HTTP协议中一个请求由三部分构成: 分别是:请求行消息头(请求头)消息正文(请求实体)。消息正文部分可以没有。

请求行

请求行是一行字符串,以连续的两个字符(回车符和换行符)作为结束这一行的标志。

  • 回车符:在ASC编码中2进制内容对应的整数是13.回车符通常用CR表示。
  • 换行符:在ASC编码中2进制内容对应的整数是10.换行符通常用LF表示。
  • 回车符和换行符实际上都是不可见字符。
请求行分为三部分:

请求方式(SP)抽象路径(SP)协议版本(CRLF) 注:SP是空格

GET / HTTP/1.1(CRLF)

URL地址格式:

协议://主机地址信息/抽象路径 http://localhost:8088 GET / HTTP/1.1

消息头

消息头是浏览器给服务端发送的一些附加信息,有的用来说明浏览器自身内容,有的用来告知服务端交互细节,有的告知服务端消息正文详情等。

消息头由若干行字符串组成,每行结束也是以CRLF标志。 每个消息头的格式为:消息头的名字(:SP)消息的值(CRLF) 消息头部分结束是以单独的(CRLF)标志。 例如:

GET / HTTP/1.1(CRLF)
Host: localhost:8088(CRLF)
Connection: keep-alive(CRLF)
Upgrade-Insecure-Requests: 1(CRLF)
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36(CRLF)
Sec-Fetch-User: ?1(CRLF)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9(CRLF)
Sec-Fetch-Site: none(CRLF)
Sec-Fetch-Mode: navigate(CRLF)
Accept-Encoding: gzip, deflate, br(CRLF)
Accept-Language: zh-CN,zh;q=0.9(CRLF)(CRLF)
消息正文

消息正文是2进制数据 , 通常是用户上传的信息,比如:在页面输入的注册信息,上传的 附件等内容。

GET / HTTP/1.1
Host: localhost:8088
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
101010101011100101.....
当客户端发送请求时,将客户端的请求行和消息正文显示出来
  1. 在ClientHandler 类中的 run方法中定义读取客户端发送请求的内容,代码如下:

    public void run() {//用于处理解析客户端发送请求 以及 响应给客户端的逻辑方法
            //处理(解析)请求
         try {
                InputStream input = socket.getInputStream();//获取输入流,准备接收请求
         int d = 0;//用来存储每次实际读取到的内容(字节)
            char cur = 'a';//cur 代表当前读取到的内容
         char per = 'a';//per 代表上次读取到的内容
            //StringBuilder 用于频繁修改字符串时的一种工具,性能好.
         StringBuilder builder = new StringBuilder();//创建一个StringBuilder
            while ((d = input.read()) != -1) {//如果读取的内容不等于-1 就一直读
             cur = (char) d;//将内容存给当前读取到的变量 cur
                //13表示回车  10表示换行
             if (per == 13 && cur == 10) {//如果上次读的内容是回车,本次是换行,代表一行结束。
                    break;//退出
             }
                builder.append(cur);//拼接当前读到的字符
             per = cur;//将本次读取的内容 存给 per 进行下次读取,那么per则装的就是上一次读取的内容
            }
         String line = builder.toString().trim();//将builder对象转换为String对象去除空白
            System.out.println(line);//打印输出每一行读取到的内容
         } catch (IOException e) {
                e.printStackTrace();
         }
        }
    如果想要全部读取,则需要循环读取,可以将读取到一行的逻辑封装成方法,便于使用:
   
  
   package webserver;
  import java.io.*;
     
  import java.net.Socket;
     
  /**
      * 处理客户端的请求与响应类
   */
     
  public class ClientHandle {
         Socket socket;
      ClientHandle(Socket socket) {
             this.socket = socket;
     }
         public void run() {//用于处理解析客户端发送请求 以及 响应给客户端的逻辑方法
          //处理(解析)请求
             try {
  
                while (true){
                 String line = readLine();
                    if(line.isEmpty()){//如果line 是空串 则表示读到最后一次的CRLF
                     break;//退出循环
                    }
                 System.out.println(line);//打印输出每一行读取到的内容
                }          
         } catch (IOException e) {
                 e.printStackTrace();
         }
        }
      private String readLine() throws IOException {
             InputStream input = socket.getInputStream();//获取输入流,准备接收请求
          int d = 0;//用来存储每次实际读取到的内容(字节)
             char cur = 'a';//cur 代表当前读取到的内容
          char per = 'a';//per 代表上次读取到的内容
             //StringBuilder 用于频繁修改字符串时的一种工具,性能好.
          StringBuilder builder = new StringBuilder();//创建一个StringBuilder
             while ((d = input.read()) != -1) {//如果读取的内容不等于-1 就一直读
              cur = (char) d;//将内容存给当前读取到的变量 cur
                 //13表示回车 10表示换行
                 if (per == 13 && cur == 10) {//如果上次读的内容是回车,本次是换行,代表一行结束
                     break;//退出
                }
                 builder.append(cur);//拼接当前读到的字符
                 per = cur;//将本次读取的内容 存给per进行下次读取,那么per则装的就是上一次读取的内容
         }
             String line = builder.toString().trim();//将builder转换为String对象去除空白
             return line;
        }
  }
     

  • 在run中调用如下图所示,再进行测试一次就能拿到完整的信息

运行测试:

  • 当控制台中显示如下:

  • 打开浏览器,在地址栏中输入localhost:8088 回车即可

  • 打开控制台查看是否是显示客户端发送的请求,如图:

响应Response

响应是服务端发送给客户端的内容。一个响应包含三部分:状态行,响应头,响应正文

状态行

状态行是一行字符串(CRLF结尾),并且状态行由三部分组成,格式为:

protocol(SP)statusCode(SP)statusReason(CRLF)

协议版本(SP)状态代码(SP)状态描述(CRLF)

例如:

HTTP/1.1 200 OK

状态代码是一个3位数字,分为5类:

1xx:保留

2xx:成功,表示处理成功,并正常响应

3xx:重定向,表示处理成功,但是需要浏览器进一步请求

4xx:客户端错误,表示客户端请求错误导致服务端无法处理

5xx:服务端错误,表示服务端处理请求过程出现了错误

具体的数字在HTTP协议手册中有相关的定义,可参阅。

状态描述手册中根据不同的状态代码有参考值,也可以自行定义。通常使用参考值即可。

响应头

响应头与请求中的消息头格式一致,表示的是服务端发送给客户端的附加信息。

Content-Type: text/html(CRLF)

Content-Length: 2546(CRLF)(CRLF)

响应正文

2进制数据部分,包含的通常是客户端实际请求的资源内容。

响应的大致内容:

HTTP/1.1 200 OK(CRLF)
Content-Type: text/html(CRLF)
Content-Length: 2546(CRLF)(CRLF)
1011101010101010101......

这里的两个响应头: Content-Type是用来告知浏览器响应正文中的内容是什么类型的数据(图片,页面等等) 不同的类型对应的值是不同的,比如:

文件类型    Content-Type对应的值
html          text/html
css           text/css
js            application/javascript
png           image/png
gif           image/gif
jpg           image/jpeg

Content-Length是用来告知浏览器响应正文的长度,单位是字节。

浏览器接收正文前会根据上述两个响应头来得知长度和类型从而读取出来做对应的处理以 显示给用户看.

上述代码完成后,我们接收了客户端的请求,现在可以任意响应给客户端一个html界面
  • 资源准备:选中项目中项目根路径文件夹右键—new—HTML File 单机, 如图所示

  • 选中后文件名字:index 回车即可

  • 双击创建好的index.html文件,内容添加如下即可:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <h1>响应成功!</h1>

</body>
</html>
  • 找到ClientHandle类,在类中run方法写关于响应客户端的代码如下:

     public void run() {//用于处理解析客户端发送请求 以及 响应给客户端的逻辑方法
            //处理(解析)请求
            try {
                File file = new File("./index.html"); //创建一个文件对象,该对象表示是根路径下的网页
                OutputStream output = socket.getOutputStream();
                //响应
                String data =  "HTTP/1.1 200 OK\r\n" +
                               "Content-Type: text/html\r\n" +
                               "Content-Length: "+file.length+"\r\n"+"\r\n";//按照规则书写响应的信息内容。
                output.write(data.getBytes());//将响应的信息写出
                FileInputStream input = new FileInputStream(file);
                int d = 0;
                while ( (d =input.read()) != -1){
                    output.write(d);//循环将读取到的文件内容写出 响应给客户端
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
  • 运行测试:

    • 运行webServer类
    • 打开浏览器输入localhost:8088 回车
    • 界面呈现如下则表示客户端接收响应成

    客户端与服务器的请求响应 一问一答实现完成

总结

  1. 了解http协议是什么?

    答:HTTP协议 超文本传输协议 由万维网制定(w3c)

    ​ 是浏览器与服务器通讯的应用层协议,规定了浏览器与服务器之间的交互规则以及交互数据的格式信息.

  2. 了解socket是什么,如何使用?

    答:在计算机领域中,Socket也被称为套接字编程,它是计算机之间进行通信的一种约定或者说是一种方式。可 以通过socket来通过互联网收发信息内容。

    服务器端ServerSocket

    在服务器端选择一个端口号,然后在指定的端口号上等待客户端发起的连接

    构造方法:

    ServerSocket(int port) 创建一个绑定特定端口号的服务器套接字
    accept() 侦听并接受到发送到此套接字的连接
    close() 关闭此套接字
    客户端Socket

    构造方法:

    Socket(String host,int port) 创建一个套接字,并且连接到host,并且绑定端口号
    close() 关闭此套接字
    getInputStream() 返回此套接字的输入流
    getOutputStram() 返回此套接字的输出流
  3. 掌握http请求信息、响应信息格式?

    请求Request

    请求是浏览器发送给服务端的内容,HTTP协议中一个请求由三部分构成: 分别是:请求行消息头(请求头)消息正文(请求实体)。消息正文部分可以没有。

    响应Response

    响应是服务端发送给客户端的内容。一个响应包含三部分:状态行,响应头,响应正文

上篇文章:入门Java编程的知识点—>socket的使用(day19)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/Z0412_J0103/article/details/141590311下篇文章: 明日发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2094205.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

带着耐心细心平常心和编程共舞

编程是什么&#xff1f;一个工具、一门技术还是一个爱好&#xff0c;不同的对待方法会带来不同的心态、产生不同的结果。编程需要扎实的基础、严密的思维和开阔的视角&#xff0c;新技术和框架日新月异&#xff0c;只有抱着科学、乐在其中的态度才能掌握高效的学习、实践方法。…

Matrix:重塑APM领域,以简驭繁的性能监控新纪元

在数字化转型的浪潮中&#xff0c;应用程序的性能监控&#xff08;APM&#xff09;已成为企业IT架构中不可或缺的一环。随着业务复杂度的提升和用户对体验要求的日益增高&#xff0c;如何高效、精准地监控并优化应用性能&#xff0c;成为了每个开发者和技术团队面临的重大挑战。…

机器学习(五) -- 监督学习(8) --神经网络1

系列文章目录及链接 上篇&#xff1a;机器学习&#xff08;五&#xff09; -- 无监督学习&#xff08;2&#xff09; --降维2 下篇&#xff1a; 前言 tips&#xff1a;标题前有“***”的内容为补充内容&#xff0c;是给好奇心重的宝宝看的&#xff0c;可自行跳过。文章内容被…

2.3导数与微分的基础与应用

1. 导数的基本概念 大家好&#xff0c;欢迎来到我们的数学大讲堂&#xff01;今天我们要聊聊一个有点酷又有点恐怖的东西——导数。别担心&#xff0c;不是让你在黑板上画曲线的那种&#xff0c;而是关于“变化率”的一种数学表达。 那么&#xff0c;什么是导数呢&#xff1f…

利用实用规模量子计算模拟宇宙中最极端的环境

华盛顿大学和劳伦斯伯克利国家实验室最近的研究展示了可扩展的技术&#xff0c;有朝一日可以实现最高能量下的基础物理实验模拟。 目录 核物理和高能物理的实用规模模拟 我们的模拟方法 Qiskit 如何使我们的实验成为可能 展望量子模拟技术的未来 粒子物理学的标准模型囊括了我们…

005.Python爬虫系列_浏览器开发者工具(详解)

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈 PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈 Oracle数…

web渗透:XXE漏洞

XXE漏洞的原理 XXE&#xff08;XML External Entity Injection&#xff09;漏洞是由于应用程序在解析XML输入时&#xff0c;没有正确处理外部实体&#xff08;External Entities&#xff09;的引用而产生的安全漏洞。XML外部实体可以引用本地或远程的内容&#xff0c;攻击者可…

大学生房屋租赁推荐系统

一、项目概述 Hi&#xff0c;大家好&#xff0c;今天分享的项目是《基于推荐算法的大学生租房交流平台》。 对于初入社会的大学生来说&#xff0c;租房是一个复杂且繁琐的过程。租房交流平台可以提供房源浏览、信息分享等&#xff0c;帮助大学生快速找到合适的房源&#xff0…

随笔2优化算法

目录 2.1 线性规划&#xff08;Linear Programming&#xff09; 2.2 非线性规划&#xff08;Nonlinear Programming&#xff09; 2.3 整数规划&#xff08;Integer Programming&#xff09; 优化算法 是数学建模中非常重要的工具&#xff0c;用于在给定的约束条件下找到某个目…

HCIP笔记13-交换(2)

一台交换机上的一个接口可以映射多个不同的MAC地址&#xff0c;但一台PC上一个MAC只能对应一个接口 三层架构--冗余--二层的桥接环路 导致的问题&#xff1a; 1.广播风暴 2.对同一数据帧的反复拷贝 3.MAC地址表翻滚 这三个问题将不断占用硬件资源&#xff0c;逐渐导致设备…

大数据基础:实时数仓发展趋势

文章目录 实时数仓发展趋势 一、​​​​​​​实时数仓现状 二、​​​​​​​​​​​​​​批流一体 实时数仓发展趋势 一、​​​​​​​​​​​​​​实时数仓现状 当前基于Hive的离线数据仓库已经非常成熟&#xff0c;随着实时计算引擎的不断发展以及业务对于实时…

oracle11g常用基本字典和动态性能字典

文章目录 Oracle11g的动态性能视图1、动态性能视图&#xff1a;2、常用的Oracle 11g动态性能视图&#xff1a;V$SESSION&#xff1a;V$SQL&#xff1a;V$SQL_PLAN&#xff1a;V$SYSSTAT&#xff1a;V$SQLSTAT&#xff1a;V$SESSION_EVENT&#xff1a;3、基本数据字典4、动态性能…

MongoDB-副本集-Replica Sets

(一) 副本集-Replica Sets 1. 简介 MongoDB中的副本集&#xff08;Replica Set&#xff09;是一组维护相同数据集的mongod服务。 副本集可提供冗余和高 可用性&#xff0c;是所有生产部署的基础。也可以说&#xff0c;副本集类似于有自动故障恢复功能的主从集群。通俗的讲就…

Linux系统性能调优全面指南

目录 一、了解系统资源 二、CPU优化 三、内存管理 四、磁盘IO优化 五、网络优化 六、监控和自动化 技巧总结表格 结语 Linux系统的性能调优是系统管理员和开发者必备的技能之一&#xff0c;用以确保服务器和应用运行的高效和稳定。本文将全面探讨Linux性能调优的各个方面…

Git之2.13版本重要特性及用法实例(五十九)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者. 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列…

【时间盒子】-【2.准备】HarmonyOS 开发前需要准备什么?

零基础新手或转行进入鸿蒙生态应用的开发者&#xff0c;请提前准备以下内容&#xff1a; 一、注册华为帐号 此帐号在华为官方各平台通用&#xff0c;比如&#xff1a;华为手机、华为商城、华为云、华为开发者联盟等等。 https://id1.cloud.huawei.com/CAS/portal/userRegist…

网络基础+Socket

目录 下图为数据分用的过程 认识IP地址 认识MAC地址 认识端口号 网络字节序 sockaddr结构 Makefile新写法 下图为数据分用的过程 认识IP地址 IP协议有两个版本, IPv4和IPv6. 我们整个的课程, 凡是提到IP协议, 没有特殊说明的, 默认都是指IPv4 IP地址是在IP协议中, 用来…

jmeter同步定时器、固定定时器、统一随机定时器详解

一、同步定时器 可以让多个线程同时向服务器发送请求&#xff0c;实现瞬间并发(相当于现实中同步秒杀商品)类似于集合点 例如&#xff1a;10个人约定去旅游&#xff0c;出发前提前会在某一个地方等到10个人同时都到了约定地点之后再一同排队上车 在任意接口下添加同步定时器模…

AWS MySQL 升级(二)—— MySQL API逻辑同步升级操作步骤

接上一篇 AWS MySQL 升级&#xff08;一&#xff09;—— 对比各类方案及原理_pg跨库查询-CSDN博客&#xff0c;由于操作步骤太多&#xff0c;单独拆出来一份。 零、 预检查 主库event_scheduler参数&#xff0c;应该为0 show variables like %event_scheduler%; binlog保留…

【荒原之梦考研数学】考研没有人支持,怎么办?

一部分考研的同学可能会发现&#xff0c;当我们上小学、初中和高中的时候&#xff0c;无论家里人还是亲戚朋友&#xff0c;都会非常支持我们的学习。 但到了考研的时候&#xff0c;我们获得的支持可能就会变得稍微小一些&#xff0c;因为这个时候&#xff0c;家里人可能想着&a…