网站栏目页如何做,企业电子商务网站建设总结,专业的新乡网站建设,wordpress meta#x1f525;博客简介#xff1a;开了几个专栏#xff0c;针对 Linux 和 rtos 系统#xff0c;嵌入式开发和音视频开发#xff0c;结合多年工作经验#xff0c;跟大家分享交流嵌入式软硬件技术、音视频技术的干货。 ✍️系列专栏#xff1a;C/C、Linux、rtos、嵌入式… 博客简介开了几个专栏针对 Linux 和 rtos 系统嵌入式开发和音视频开发结合多年工作经验跟大家分享交流嵌入式软硬件技术、音视频技术的干货。 ✍️系列专栏C/C、Linux、rtos、嵌入式开发、流媒体、数据结构、网络协议、开源库、CMake、Makefile、架构设计模式等。 文章目录 一、前言二、HTTP 概述三、HTTP 的特性四、HTTP 工作流程五、HTTP 请求方法六、HTTP 请求格式七、HTTP 响应格式八、HTTP 的优缺点九、示例 《HTTP总结与全梳理》系列主要是针对HTTP协议知识点进行全面的梳理总结。此篇文章主要对HTTP协议进行详解并列举一个简单的示例demo该系列后续文章包括HTTP 开发调试方法抓包方法、HTTP数据上传HTTP数据下载等文章。
一、前言
嵌入式开发工作中我们常用到一些网络协议本章我们总结http协议后续文章我们会陆续总结https等网络协议。在总结http协议之前我们先熟悉一下什么是超文本。 超文本的概念最早由Ted Nelson在1960年代提出并在1990年代因万维网World Wide Web的发展而广为人知。 超文本Hypertext是一种通过HTML超文本标记语言组织和呈现信息的方式。允许读者通过点击或选择文本中的链接来跳转到相关的信息或内容这种链接通常称为“超链接”Hyperlinks。 在超文本中内容可以包含文本、图像、视频等多种媒体形式并且这些内容之间可以通过超链接进行连接和跳转。这种非线性的信息组织方式使得用户能够灵活地浏览和查找信息而不是按照传统的线性文本顺序进行阅读。 例如在一个网页中您会发现许多链接当您点击一个链接时它会带您到另一个相关的页面或内容这就是典型的超文本应用。 二、HTTP 概述
1. HTTP 发展历程 HTTP的发展可以追溯到1990年代初期。它经历了几个主要版本的演变每个版本都带来了显著的改进和优化。以下是HTTP历次发展的详细历程 1. HTTP/0.91991年 HTTP的第一个版本是在1991年由WWW之父蒂姆·伯纳斯-李Tim Berners-Lee提出的。这是一个极其简陋的协议只有一个GET方法用于请求服务器上的HTML文档。它没有HTTP头部因此无法传输元数据所有的响应都被视为纯文本。该版本缺少如下现代HTTP特性 方法 只有一个GET没有POST、PUT等。 协议头 没有请求和响应头。 状态码 没有标准化的状态码。 2. HTTP/1.01996年 HTTP/1.0是第一个广泛使用的版本并在1996年通过RFC 1945标准化。它引入了以下显著改进 更多的方法 除了GET新增了POST和HEAD方法。 协议头 引入了HTTP头部信息使请求和响应更加灵活与可扩展。 状态码 标准化了状态码如200 OK、404 Not Found等。 多媒体支持 支持图片、文件下载等多种媒体类型的传输。 3. HTTP/1.11997年 HTTP/1.1首次在RFC 2068中定义并在随后通过RFC 2616进行了修订和完善。它成为了至今最为广泛应用的HTTP版本带来了多个关键特性和性能改进 持久连接默认保持连接允许多个请求和响应复用同一个TCP连接减少了连接建立和关闭的开销。 分块传输编码 支持服务器在文档生成的同时发送响应从而实现动态内容的高效传输。 增强的缓存机制 引入了强缓存控制如Cache-Control头和条件请求如If-Modified-Since头。 Host头 支持在一个服务器上托管多个域名从而实现虚拟主机功能。 管道化 允许在同一连接上并行发送多个请求而不用等待前一个请求的响应但这个特性在实践中未得到广泛使用。 4. HTTP/2.02015年 HTTP/2由IETF在2015年发布RFC 7540其设计目标是改善HTTP/1.x的性能瓶颈主要通过以下技术实现 二进制分帧 使用二进制协议替代文本协议提升了解析速度和传输效率。 多路复用 在同一个TCP连接上并发地传输多个请求和响应减少了延迟并提高了网络利用率。 头部压缩 采用HPACK算法压缩HTTP头部减少头部信息的传输开销。 服务器推送 允许服务器主动向客户端推送资源以提前加载页面所需资源提升响应速度。 5. HTTP/32022 还在完善中 HTTP/3是最新一代的HTTP协议目前正处在标准化过程当中部分草案已经由IETF发布。HTTP/3的关键区别在于它基于QUICQuick UDP Internet Connections协议而不是传统的TCP。QUIC是Google开发的一种基于UDP的协议旨在解决TCP的延迟和连接可靠性问题。HTTP/3的主要特点包括 基于UDP的QUIC协议通过使用UDP来替代TCP减少了连接建立时间和抗网络抖动的能力。 快速重连 在网络改变或中断时实现快速重连而不需要重新建立连接。 改进的流控制在HTTP/3中多个流之间完全独立减少了拥塞和阻塞问题。 未来的发展 HTTP仍在不断演进中以适应日益增长的互联网需求和新兴的网络技术。每个新版本的发布都致力于解决前一个版本中的缺陷和优化网络性能。 2. HTTP 简述 HTTP全称为 Hypertext Transfer Protocol中文含义为“超文本传输协议”。 HTTP协议是一个基于请求/响应模式的应用层协议。
HTTP往往是基于TCP/IP协议传输数据但也有HTTP是基于UDP协议来传输数据。通过上面讲述的HTTP发展历程可知HTTP1.0、HTTP1.1、HTTP2.0均是基于TCP实现而HTTP3则是基于UDP实现。
HTTP协议定义了客户端与服务器之间的通信规范以实现对各种资源如文本、图像、音频、视频等的传输和访问。通常由HTTP客户端发起一个请求创建一个到服务器指定端口默认是80端口的TCP连接。HTTP服务器则在那个端口监听客户端的请求。一旦收到请求服务器会向客户端返回一个状态比如HTTP/1.1 200 OK以及返回的内容如请求的文件、错误消息、或者其它信息。
OSI参考模型和TCP/IP分层模型示意图为
三、HTTP 的特性
无状态 HTTP是无状态协议这意味着每个请求都是独立的服务器不保留任何有关之前请求的信息。这种设计使得HTTP具有很高的灵活性和可扩展性但也带来了会话管理的挑战通常通过Cookies、Session等机制实现。 无连接 HTTP的“无连接”特性指的是每次HTTP请求与响应之间并不要求客户端和服务器之间保持长时间的通信连接。具体来说客户端在发送请求并接收到服务器的响应后连接就会被立即关闭这样的设计使得每个请求/响应对都独立于其他请求/响应对。 虽然HTTP协议本身是无连接的但其具体实现上有所不同 短连接 短连接短链接是HTTP/1.0协议默认使用的一种连接方式。特性如下 每个请求/响应对结束后立刻关闭连接 在HTTP/1.0中客户端和服务器的每次请求/响应对都会建立一个新的TCP连接并在请求完成后关闭连接。高连接开销 由于每次请求都要重新建立和关闭连接短连接会导致较高的连接开销。适用于低频率的请求 短连接适用于那些不频繁发送请求的情况但当请求频繁时会带来额外的负载和延时。 长连接 长连接长链接是HTTP/1.1及以上版本默认支持和推荐的连接方式。长连接并不是一直保持连接不断开而是在一定的时间范围内保持连接以便可以复用已有的连接来处理多个请求和响应。特性如下 连接保持一段时间: 长连接在请求完成后不会立即关闭可以保持TCP连接一定时间通常这个时间由服务器设置的一段超时时间决定。在此连接期间客户端可以继续发送多个请求。HTTP/1.1及以上版本默认使用长连接Connection: keep-alive不需要显式指定。如果不使用长连接需要明确指定Connection: close不使用长连接。减少连接开销 由于减少了重复的TCP握手和连接建立、关闭的过程长连接显著降低了连接开销提高了请求效率和响应速度。支持多个请求/响应对 在一个长连接上客户端可以发送多个请求每个请求可以在不同的时候被发送。例如浏览器可以在一个长连接上不断地获取网页上的多个资源图片、CSS文件、JavaScript等。 四、HTTP 工作流程
HTTP协议采用了请求/响应模型定义Web客户端如何从Web服务器请求Web页面以及服务器如何把Web页面传送给客户端。客户端向服务器发送一个请求报文请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。 以下是 HTTP 请求/响应的步骤 1. 客户端连接到Web服务器 一个HTTP客户端通常是浏览器与Web服务器的HTTP端口默认为80建立一个TCP套接字连接。例如http://www.baidu.com。 2. 发送HTTP请求 通过TCP套接字客户端向Web服务器发送一个文本的请求报文一个请求报文由请求行、请求头部、空行和请求数据4部分组成。 3. 服务器接受请求并返回HTTP响应 Web服务器解析请求定位请求资源。服务器将资源复本写到TCP套接字由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。 4. 释放连接TCP连接 若connection 模式为close则服务器主动关闭TCP连接客户端被动关闭连接释放TCP连接;若connection模式为keepalive则该连接会保持一段时间在该时间内可以继续接收请求; 5. 客户端浏览器解析HTML内容。客户端浏览器首先解析状态行查看表明请求是否成功的状态代码。然后解析每一个响应头响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML根据HTML的语法对其进行格式化并在浏览器窗口中显示。 HTTP协议规定,请求从客户端发出,最后服务器端响应该请求并返回。换句话说,肯定是先从客户端开始建立通信的,服务器端在没有接收到请求之前不会发送响应。
五、HTTP 请求方法
方法描述GET用于获取服务器上的资源。当客户端发送GET请求时服务器将返回相应请求的资源 ,GET请求的参数会附在URL后面因此可能会受到长度限制HEAD类似于GET请求但只返回资源的报头信息而不返回实际的资源内容。HEAD请求常用于检查资源的元数据例如最后的修改时间、ETag等POST用于向服务器提交数据并请求服务器进行处理。POST请求通常用于向服务器发送表单数据、上传文件、进行用户登录等操作。相对于GET请求POST请求没有长度限制并且不会将参数暴露在URL中而是放在请求体中进行传输PUT用于创建或更新服务器上的资源。PUT请求类似于POST请求但PUT请求要求在指定的URL上创建或更新资源。如果资源已存在则会进行更新如果资源不存在则会进行创建DELETE用于删除服务器上的资源。DELETE请求会删除指定URL对应的资源。删除后相应的URL将不再存在。CONNECT主要用于代理服务器指示代理服务器与目标服务器建立隧道连接OPTIONS用于获取目标URL所支持的请求方法。服务器收到OPTIONS请求后会返回该URL所支持的请求方法列表TRACE用于将请求上的报头信息回显给客户端用于调试或诊断信息
在实际嵌入式开发中上述方法大部分都使用不到最常见的HTTP方法是GET、PUT、POST。
六、HTTP 请求格式
客户端发送一个HTTP请求到服务器的请求消息格式包括请求行、请求头、空行、请求体请求数据四部分组成 下图示例
请求头里面的这些键值对含义看下表
请求头作用示例Host指定请求的目标主机的域名和可选的端口号Host: www.example.comUser-Agent包含发出请求的浏览器或客户端的信息User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)Accept告知服务器客户端能够处理的内容类型Accept: text/html;image/apngAccept-Language指定客户端首选的自然语言Accept-Language: zh-CNAccept-Encoding指定客户端支持的内容编码方式如压缩算法Accept-Encoding: gzip, deflateCookie包含之前由服务器发送并存储在客户端的cookieCookie: sessionIdabc123; logged_intrueReferer告知服务器请求来源引荐资源的URLReferer: https://www.google.com/Connection控制连接的处理Connection: keep-aliveContent-Type告知服务器请求主体包含的数据的类型Content-Type: application/jsonContent-Length表示请求主体的长度以字节为单位Content-Length: 16Authorization包含认证信息用于身份验证Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQCache-Control指示请求和响应的缓存机制Cache-Control: no-cacheRange请求特定范围的资源部分它是断点续传的基础Range: bytes500-999
需要注意的是这个Content-Length表示请求体里面的数据长度即“nameuenoage37”长度正好为16
七、HTTP 响应格式
HTTP响应也由四部分组成分别是响应行、响应头、空行和响应体响应正文。 下图示例
响应头里面的这些键值对含义看下表
响应头作用示例Date指明响应被发送的日期和时间Date: Wed, 21 Oct 2023 07:28:00 GMTServer包含处理请求的服务器软件的信息Server: Apache/2.4.41 (Ubuntu)Content-Type指示响应主体的数据类型Content-Type: text/html; charsetUTF-8Content-Length表示响应主体的长度以字节为单位Content-Length: 169Content-Encoding指示服务器对响应主体使用的编码方式Content-Encoding: gzipLast-Modified表示所请求资源的最后修改日期和时间Last-Modified: Wed, 21 Oct 2015 07:28:00 GMTETag提供资源的特定版本标识符用于缓存优化ETag: “5d8c72a5edda3f30b6cf15e66f3591b2”Accept-Ranges指示服务器是否支持范围请求及范围单位Accept-Ranges: bytesCache-Control告诉客户端如何缓存响应Cache-Control: no-cache, no-store, must-revalidateExpires指定响应过期的日期和时间过期后需要重新请求Expires: Wed, 21 Oct 2024 07:28:00 GMTSet-Cookie设置HTTP cookie发送到客户端以存储信息Set-Cookie: sessionIdabc123; Path/; HttpOnlyLocation用于重定向响应告知客户端重新请求的位置URLLocation: https://www.example.com/newpageConnection控制当前连接的管理Connection: keep-aliveTransfer-Encoding指示响应主体的传输编码方式用于分块传输Transfer-Encoding: chunkedRetry-After告知客户端多久之后可以再次请求资源通常用于503状态码Retry-After: 120
需要注意的是所有HTTP响应的第一行都是状态行即响应行就是状态行。状态行内容依次是当前HTTP版本号3位数字组成的状态码以及描述状态的短语彼此由空格分隔。状态码的第一个数字代表当前响应的类型如下图 关于HTTP详细的状态码可查看开发文档 HTTP 响应状态码 关于HTTP更多内容详细可查看开发文档 HTTP 开发文档
八、HTTP 的优缺点
以下是HTTP的优点和缺点
优点
简单且易于实现 HTTP协议结构简单快速且易于实现对于开发和调试非常方便。广泛支持 几乎所有的现代互联网应用和设备都支持HTTP使其成为一个非常通用的协议。无状态性 HTTP是无状态协议这意味着每个请求都是独立的不依赖于前面的请求。这简化了服务器设计和应用逻辑。兼容性好 HTTP可以使用不同的传输层如TCP、QUIC等这使得它在不同的网络环境中具有良好的兼容性。支持多种媒体类型 HTTP可以传输各种类型的数据如HTML文档、图像、视频、JSON、XML等。
缺点
无状态性 尽管无状态性使得HTTP简单易实现但它也导致了每次请求/响应之间不能保留客户端的状态需要使用cookie、session等技术来实现状态保存。安全性较低 原生的HTTP不加密明文传输数据在传输过程中容易被截取和篡改。HTTPSHTTP SSL/TLS可以解决这个问题但增加了复杂度和性能开销。性能问题 HTTP/1.1的请求/响应模型使得每次请求都要建立新的TCP连接或复用已有连接但仍会带来延迟和开销。在HTTP/2和HTTP/3中有所改进但也增加了复杂度。冗长的头部 HTTP协议的请求和响应中头部信息较为冗长占用了额外的带宽。资源误用 无状态性和握手开销使得HTTP在大量短连接情况下比较消耗服务器资源。
九、示例
示例通过http的GET方法连接www.example.com并获取其响应打印出来。www.example.com的界面如下
1、目录结构
project
└── http.c2、http.c源码
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include arpa/inet.h
#include netdb.h#define BUFFER_SIZE 4096void error_handling(const char *message)
{perror(message);exit(EXIT_FAILURE);
}int main()
{const char *hostname www.example.com;const char *portnum 80;const char *path /;int sockfd;struct addrinfo hints, *res;char buffer[BUFFER_SIZE];int bytes_received;memset(hints, 0, sizeof(hints));hints.ai_family AF_UNSPEC;hints.ai_socktype SOCK_STREAM;if (getaddrinfo(hostname, portnum, hints, res) ! 0) {error_handling(getaddrinfo() error);}sockfd socket(res-ai_family, res-ai_socktype, res-ai_protocol);if (sockfd -1) {error_handling(socket() error);}if (connect(sockfd, res-ai_addr, res-ai_addrlen) -1) {error_handling(connect() error);}freeaddrinfo(res);snprintf(buffer, sizeof(buffer),GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n,path, hostname);printf(*********Request*********\n);printf(%s, buffer);if (write(sockfd, buffer, strlen(buffer)) -1) {error_handling(write() error);}while ((bytes_received read(sockfd, buffer, BUFFER_SIZE - 1)) 0) {buffer[bytes_received] \0;printf(*********Response*********\n);printf(%s, buffer);}if (bytes_received -1) {error_handling(read() error);}close(sockfd);return 0;
}3、编译运行 在project目录执行命令生成可执行文件app
gcc -o app http.c 运行结果 请求报文 响应报文