【JavaWeb】初识HTTP

JavaWeb之HTTP学习

1、HTTP相关基本概念

  • 什么是HTTP

    HTTP(HyperText Transfer Protocol,超文本传输协议是一个简单的请求-响应协议,它通常运行在TCP之上

    其主要作用是用于客户端和服务端的通信的规范,即:

    1. 请求:客户端应该发送什么样的请求数据给服务端,规定请求的形式
    2. 响应:服务端收到客服端的请求数据应该做出什么样的响应,规定响应的形式

    image-20220731134741725

    HTTP好比是一座桥梁,用于连接客户端和服务端。类比生活中的事情,当我们要和外国人交流,不可能你说中文、他说日语,这就会导致沟通障碍(当然这个例子也不太恰当,因为有些人可能两种语言都懂),为了方便交流我们就会选择一种语言当作中间语言,而这个中间语言就好比HTTP,中国人和外国人就好比客户端和服务端。

    学习HTTP主要就是学习请求和响应数据的具体格式内容。

  • HTTP的特点

    1)安全可靠。因为HTTP协议是基于TCP协议的

    2)一次请求对应一次响应。因为HTTP是基于请求-响应模型的

    3)对事物的处理没有记忆能力。因为HTTP协议是无状态1协议,对于每次事物的处理都是独立的,所以对事物的处理没有记忆能力

  • HTTP的优点和缺点

    1)优点

    灵活性高扩展性强。每当应用程序需要其他功能时,HTTP都可以下载扩展或插件并显示相关数据

    可靠传输。HTTP是基于TCP协议的

    数据传输快。第一,HTTP对事物处理没有记忆能力,无需在意之前请求和响应的数据;第二,只有当连接建立时,握手过程才会发生在HTTP中。因此,请求之后不会有握手过程。这显着减少了连接中的延迟

    2)缺点

    明文传输不安全。使用HTTP进行明文传输数据,很容易被人通过抓包获取数据

    无法复用同一TCP连接。复用同一个TCP连接会导致队头阻塞2

    多次请求之间的数据无法共享。因为HTTP对事物的处理没有记忆能力,每一次请求-响应都是独立的。(但是Java早已想到了这个问题,所以提出了会话技术CookieSession来解决这个问题Java就是碟

2、数据格式介绍

2.1 请求的数据格式

image-20220801084832683 image-20220801084846699
  • 请求数据的组成请求行+请求头+[请求体]

    1)请求行:位于请求数据的第一行,格式为:请求方式 /请求的资源路径 协议名称/协议版本号 。HTTP的请求方式共有七种3,常见的有两种,分别是GET请求和POST请求

    2)请求头:从第二行开始,格式为:key: value

    常见的请求头:

    • Host: 表示请求的主机名
    • Connection: 请求连接的方式。一般默认是keep-alive,表示请求建立长连接
    • User-Agent: 表示浏览器的版本。例如Chrome浏览器的标识类似Mozilla/5.0 …Chrome/79,IE浏览器的标识类似Mozilla/5.0(Windows NT …)like Gecko
    • Accept:表示浏览器能接收的资源类型。如text/,image/或者*/*表示所有
    • Accept-Language:表示浏览器偏好的语言。服务器可以据此返回不同语言的网页
    • Accept-Encoding:表示浏览器可以支持的压缩类型。例如gzip, deflate等

    3)请求体:位于最后一行,用于存放请求参数,GET请求不具有,格式:key=value&...

  • GET请求和POST请求的区别

    1)请求参数存放位置不同。GET请求没有请求体,请求参数存放在请求行中;而POST请求具有,请求参数存放再请求体中

    2)请求参数的限制不同。GET请求请求参数大小有限制,POST没有

    比较GET与POST

2.2 响应的数据格式

image-20220801090724717
  • 响应数据的组成响应行+响应头+响应体

    1)响应行:位于响应数据的第一行,格式为:协议名称/协议版本号 响应码 状态码

    常见响应码(1xx~5xx):

    状态码分类说明
    1xx响应中——临时状态码,表示请求已经接受,告诉客户端应该继续请求或者如果它已经完成则忽略它
    2xx成功——表示请求已经被成功接收,处理已完成
    3xx重定向——重定向到其它地方:它让客户端再发起一个请求以完成整个处理。
    4xx客户端错误——处理发生错误,责任在客户端,如:客户端的请求一个不存在的资源,客户端未被授权,禁止访问等
    5xx服务器端错误——处理发生错误,责任在服务端,如:服务端抛出异常,路由出错,HTTP版本不支持等
    • 200 ok :客户端请求成功
    • 400:服务端无法识别请求(一般是客户端请求的数据存在语法错误)
    • 404 Not Found :请求资源不存在(一般是URL错误,或者资源被移除)
    • 500 Internal Server Error :服务端发生不可预期的错误(一般是Java代码出现异常,建议去看日志文件)

    状态码大全:HTTP中文开发手册


    推荐阅读:Http响应码分类汇总

    2)响应头:从第二行开始,格式为:key: value

    常见的响应头:

    • Server:表示服务器以及服务器的版本号,例如:Tengine/1.4
    • Content-Type:表示该响应内容的类型,例如:text/html,image/jpeg
    • Content-Length:表示该响应内容的长度(字节数)
    • Content-Encoding:表示该响应压缩算法,例如gzip
    • Cache-Control:指示客户端应如何缓存,例如max-age=300表示可以最多缓存300秒

    3)响应体:是响应数据的最后一部分,用于存放响应后的数据,是html格式

案例

模拟客户端访问服务端,服务端给发送请求数据

image-20220801230412938

pom.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hhxy</groupId>
    <artifactId>day5_http</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>16</maven.compiler.source>
        <maven.compiler.target>16</maven.compiler.target>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

    </dependencies>

</project>

Java代码:

package com.hhxy.http;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
/*
    自定义服务器
 */
public class Server {
    public static void main(String[] args) throws IOException {
        //1、获取ServerSocket对象,注册端口号
        ServerSocket ss = new ServerSocket(8080); // 监听指定端口
        System.out.println("server is running...");//测试代码
        //2、重复接收客户端发送的信息
        while (true){
            //3、于客户端建立Socket管道连接
            Socket sock = ss.accept();
            //测试代码,获取远程客户端的IP地址
            System.out.println("connected from " + sock.getRemoteSocketAddress());
            //4、创建线程,并执行任务
            Thread t = new Handler(sock);
            t.start();
        }
    }
}

/**
 * 线程类
 */
class Handler extends Thread {
    Socket sock;//服务端每次接收的来自不同客户端Socket对象

    public Handler(Socket sock) {
        this.sock = sock;
    }

    /**
     * 服务端运行的方法
     */
    public void run() {
        try (InputStream input = this.sock.getInputStream()) {//处理来自客户端的信息
            try (OutputStream output = this.sock.getOutputStream()) {//处理服务端发送的信息
                handle(input, output);//客户端进行响应
            }
        } catch (Exception e) {
            try {
                this.sock.close();
            } catch (IOException ioe) {
            }
            System.out.println("client disconnected.");
        }
    }

    /**
     * 线程类的核心方法:用于服务端处理HTTP请求数据,以及向客户端发送响应数据
     * @param input
     * @param output
     * @throws IOException
     */
    private void handle(InputStream input, OutputStream output) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
        // 读取HTTP请求:
        boolean requestOk = false;
        String first = reader.readLine();
        if (first.startsWith("GET / HTTP/1.")) {
            requestOk = true;
        }
        for (;;) {
            String header = reader.readLine();
            if (header.isEmpty()) { // 读取到空行时, HTTP Header(请求头)读取完毕
                break;
            }
            System.out.println(header);//打印请求行和请求头
        }
        System.out.println(requestOk ? "Response OK" : "Response Error");//打印服务器是否响应成功的信息
        if (!requestOk) {
            // 发送错误响应:
            writer.write("HTTP/1.0 404 Not Found\r\n");
            writer.write("Content-Length: 0\r\n");
            writer.write("\r\n");
            writer.flush();
        } else {
            // 发送成功响应:

            //读取html文件,转换为字符串
            BufferedReader br = new BufferedReader(new FileReader("html/hello.html"));
            StringBuilder data = new StringBuilder();
            String line = null;
            while ((line = br.readLine()) != null){
                data.append(line);
            }
            br.close();
            int length = data.toString().getBytes(StandardCharsets.UTF_8).length;
            //向客户端发送响应行和响应头的信息
            writer.write("HTTP/1.1 200 OK\r\n");
            writer.write("Connection: keep-alive\r\n");
            writer.write("Content-Type: text/html\r\n");
            writer.write("Content-Length: " + length + "\r\n");
            writer.write("\r\n"); // 空行标识Header和Body的分隔
            //向客户端发送响应体的信息
            writer.write(data.toString());
            writer.flush();
        }
    }
}

image-20220801230542061


  1. 无状态指的是客户端发送HTTP请求给服务端之后,服务端根据请求响应数据,响应完后,不会记录任何信息 ↩︎

  2. 队头阻塞简而言之,就是如果一个响应返回延迟了,那么其后续的响应都会被延迟,直到队头的响应送达 ↩︎

  3. 七种方式,分别为:GET方法、POST方法、HEAD方法、PUT方法、DELETE方法、CONNECT方法、OPTIONS方法、TRACE方法 ↩︎

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知识汲取者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值