当前位置: 首页 > news >正文

HTTP 快速解析

一、HTTP请求结构

HTTP请求和响应报文由以下部分组成(以请求报文为例):

  • 请求报文结构:

    1. 请求行:包含HTTP方法(如GET/POST)、请求URL和协议版本(如HTTP/1.1,HTTP/2.0,HTTP/3.0),格式为 方法 URL 协议版本
    2. 请求头(Headers):包含元数据如 Host(目标域名)、Content-Length(报文主体长度)、Accept(客户端支持的数据格式)等。
    3. 空行:用于分隔请求头和报文主体。
    4. 报文主体:通常为请求参数(GET方法无主体)或JSON/表单数据(POST/PUT方法)。

    在这里插入图片描述

  • 响应报文结构:状态行(含状态码)、响应头、空行、响应主体。

    在这里插入图片描述


二、常用HTTP状态码分类

1. 1xx(信息性状态码)

  • 100 Continue:服务器已接收请求头,客户端可继续发送请求体。
  • 101 Switching Protocols:协议切换(如WebSocket)

2. 2xx(成功状态码)

  • 200 OK:请求成功,返回完整数据。
  • 204 No Content:请求成功但无返回数据(如DELETE操作)。
  • 206 Partial Content:返回部分资源(如断点续传)

3. 3xx(重定向状态码)

  • 301 Moved Permanently:资源永久迁移,搜索引擎需更新URL。
  • 304 Not Modified:客户端缓存有效,服务器不返回新内容。
  • 307 Temporary Redirect:临时重定向,保留原始请求方法(如POST)。

4. 4xx(客户端错误)

  • 400 Bad Request:请求语法错误。
  • 403 Forbidden:服务器拒绝请求(权限不足)。
  • 404 Not Found:资源不存在。

5. 5xx(服务器错误)

  • 500 Internal Server Error:服务器内部错误。
  • 503 Service Unavailable:服务器过载或维护。

三、状态码使用场景

1. 206 Partial Content

  • 场景:客户端通过 Range 头请求资源的某部分(如大文件分块下载或视频流播放)。
  • 示例:
    GET /large-file.mp4 HTTP/1.1
    Range: bytes=0-999
    
    服务器返回 206 Partial Content 和对应数据块。

2. 304 Not Modified

  • 场景:客户端携带 If-Modified-Since(最后修改时间)或 If-None-Match(ETag)请求资源,服务器验证后确认未修改。
  • 流程:
    1. 客户端首次请求,服务器返回资源及 Last-ModifiedETag
    2. 客户端再次请求时携带上述字段,服务器返回 304,客户端使用本地缓存。

小结

206 用于分块传输,304 用于缓存优化,两者均减少网络传输量。


四、HTTP缓存机制

1. 强制缓存

  • 原理:客户端直接使用本地缓存,无需请求服务器。
  • 控制字段:
    • Cache-Control: max-age=3600(缓存3600秒)。
    • Expire: Wed, 20 Jan 2026 12:00:00 GMT(过期时间)。
  • Cache-Control 的优先级高于 Expires

2. 协商缓存

  • 原理:客户端与服务器协商是否使用缓存。
  • 实现方式:
    • Last-Modified:客户端发送 If-Modified-Since,服务器比对时间。
    • ETag:客户端发送 If-None-Match,服务器校验资源哈希值。
  • 优先级:ETag > Last-Modified(更精确)。

    Last-Modified基于时间实现,ETag是基于唯一标识实现,故而ETag可以避免由于时间篡改导致的不可信问题。

  • 304 Not Modified:客户端缓存有效,服务器不返回新内容。
  • 使用时与强制缓存配合使用,只有强制缓存失效才会使用协商缓存。

3. 缓存失效

  • 主动失效:服务器通过 Cache-Control: no-cacheCache-Control: no-store 强制客户端重新请求。
  • 被动失效:资源更新后,客户端下次请求会触发重新校验。

小结

HTTP缓存通过强制和协商机制提升性能,开发者需根据场景选择合适策略(如静态资源用强制缓存,动态内容用协商缓存)。


五、应用

基于 Java 原生 HttpURLConnection 的文件下载:

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;public class FileDownloadExample {public static void main(String[] args) {URL url = new URL("https://blog.csdn.net/xiaolingting?type=blog");HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();urlConnection.setRequestMethod("GET");urlConnection.setConnectTimeout(5000);urlConnection.setReadTimeout(10000);int responseCode = urlConnection.getResponseCode();if (responseCode != HttpURLConnection.HTTP_OK) {System.out.println("download error");return;}
// 1.0 传统方式   try (InputStream inputStream = urlConnection.getInputStream();FileOutputStream download = new FileOutputStream("download");) {BufferedInputStream bis = new BufferedInputStream(inputStream);BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(download);int bytesRead = 0;byte[] buffer = new byte[4 * 1024];while ((bytesRead = bis.read(buffer))  != -1) {bufferedOutputStream.write(buffer, 0, bytesRead);}} catch (IOException e) {throw new RuntimeException(e);}// 2.0 NIO 优化
// 		try(InputStream inputStream = urlConnection.getInputStream();
//            FileChannel download = FileChannel.open(Paths.get("download"),
//                    StandardOpenOption.CREATE, StandardOpenOption.WRITE,StandardOpenOption.READ)) {
//
//            MappedByteBuffer mapBuffer = download.map(FileChannel.MapMode.READ_WRITE, 0,
//                    urlConnection.getContentLength());
//
//            int bytesRead = 0;
//            byte[] buffer = new byte[4 * 1024];
//            while ((bytesRead = inputStream.read(buffer))  != -1) {
//                mapBuffer.put(buffer, 0, bytesRead);
//            }
//
//
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }        urlConnection.disconnect();}
}

代码说明

  1. HTTP 连接建立

    • 使用 HttpURLConnection 建立与目标 URL 的连接,设置超时时间避免阻塞。
  2. 响应码检查

    • 通过 connection.getResponseCode() 获取响应码,仅当状态码为 200 OK 时继续下载。
  3. 流处理

    • 输入流:通过 connection.getInputStream() 获取服务器返回的字节流。
    • 缓冲流:使用 BufferedInputStreamBufferedOutputStream 提升读写效率。
    • 分块读取:通过 4KB 缓冲区循环读取数据,避免大文件内存溢出。
  4. 异常处理

    • 使用 try-with-resources 自动关闭流,防止资源泄漏。
    • 捕获 IOException 处理网络或IO错误。

扩展功能

  1. 断点续传
    添加 Range 请求头指定下载范围:

    connection.setRequestProperty("Range", "bytes=0-");
    

    处理 206 Partial Content 状态码。

    if (responseCode == HttpURLConnection.HTTP_PARTIAL) { // 206 Partial Content//  获取输入流并计算总文件大小try (InputStream inputStream = connection.getInputStream;RandomAccessFile file = new RandomAccessFile(savePath, "rw")) {// 跳过已下载的字节位置file.seek(file.length);byte[] buffer = new byte[4 * 1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {file.write(buffer, 0, bytesRead);downloadedBytes += bytesRead;updateCheckpoint(checkpointFile, downloadedBytes); // 更新断点记录}}
    }
  2. 进度监控
    while 循环中累加已读字节数,结合总文件大小(从 Content-Length 头获取)计算下载进度。

  3. MD5 校验
    添加 ETagLast-Modified 头验证文件一致性。


注意事项

  • HTTPS 支持:需处理证书问题(默认信任所有证书可能不安全),参考HTTPS实现安全的关键方法及技术细节。
  • 大文件下载:建议使用 NIO 或异步流提升性能。
  • 生产环境:推荐使用 Apache HttpClient 或 OkHttp 等成熟库。

六、其它细节

1、HTTP版本差异

  • HTTP/1.1使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。
  • HTTP/2.0 协议是基于 HTTPS 的,即 HTTP/2.0 的安全性是有保障的。
  • HTTP/1.1 和 HTTP/2.0 传输协议使用的是 TCP 协议,而到了 HTTP/3.0 传输协议改用了 UDP 协议。

关于HTTPS细节可以参考HTTPS实现安全的关键方法及技术细节

http://www.xdnf.cn/news/231463.html

相关文章:

  • php+mysql活动报名学生选课产品预定旅游报名系统网站源码
  • Spyglass:官方Hands-on Training(一)
  • 【容器化】Linux环境Docker在线与离线安装手册
  • vscode中设置eslint保存时自动格式化未生效
  • 网易爆米花 1.8.8 | 免费无广告,支持多网盘聚合和智能刮削技术,提供顶级画质和逼真音效的影视管理应用
  • 【大模型系列篇】Qwen3开源全新一代大语言模型来了,深入思考,更快行动
  • Python 用一等函数重新审视“命令”设计模式
  • CMake解析参数用法示例
  • 【模型量化】量化基础
  • 大连理工大学选修课——机器学习笔记(7):集成学习及随机森林
  • 三生原理与中华文明标识体系的关系?
  • vs2019编译occ7.9.0时,出现fatal error C1060: compiler is out of heap space
  • C++(初阶)(十六)——set
  • YOLO视觉模型可视化训练与推理测试工具
  • 嵌入式中常用的算法介绍
  • (Go Gin)Gin学习笔记(五)会话控制与参数验证:Cookie使用、Sessions使用、结构体验证参数、自定义验证参数
  • 自动驾驶-一位从业两年的独特视角
  • 2025年-redis(p1-p10)
  • Kotlin与Jetpack Compose的详细使用指南
  • 高级java每日一道面试题-2025年4月30日-基础篇[反射篇]-如何防止你的类被通过反射非法实例化?
  • PCI总线数据采集卡 32路多功能异步模拟量信号采集卡
  • 如何在 Go 中实现各种类型的链表?
  • 硬盘分区丢失≠末日!3步逻辑恢复法+物理修复全流程图解
  • 大数据应用开发和项目实战-Seaborn
  • 使用通义千问大模型做结构化输出报错的分析
  • ubantu部署yolov5(第四集:模型加速)
  • 正点原子STM32H743单片机实现ADC多通道检测
  • k8s平台:手动部署Grafana
  • SQL命令二:SQL 高级查询与特殊算法
  • Git从入门到精通-第一章-基础概念