应用层HTTP协议


img

应用层HTTP协议

1、HTTP协议概念

在前面的博客中我们有提到网络版计算器,其中Calculate.hpp文件就是应用层,也就是我们程序员需要做的一些功能,Protocol.hpp文件并不是应用层协议,而是我们的自定义的表示层(负责数据格式转换、加密解密)。而HTTP(HyperText Transfer Protocol,超文本传输协议)是一个至关重要的协议。它定义了客户端(如浏览器)与服务器之间如何通信,以交换或传输超文本(如 HTML 文档)。

HTTP 协议是客户端与服务器之间通信的基础。客户端通过 HTTP 协议向服务器发送请求,服务器收到请求后处理并返回响应。HTTP 协议是一个无连接、无状态的协议,即每次请求都需要建立新的连接(HTTP/1.1不需要),且服务器不会保存客户端的状态信息。


2、URL(统一资源定位符)

我们平时访问的网址其实就是URL。

小知识,一般域名就是IP地址。

我们可以看到,这里域名加端口就是IP+端口,可以唯一确定互联网上的一台主机或服务器。

注意,在路径那里,/不一定表示的是根目录,可能是当前代码的一个文件夹目录,比如./wwwroot,现在不懂,在后面的代码实现里面就懂了。


2.1、URL的encode(编码)和decode(解码)

/?:等这样的字符,已经被 url 当做特殊意义理解了。因此这些字符不能随意出现。

比如,某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义。

转义的规则如下:

将需要转码的字符转为 16 进制,然后从右到左,取 4 位(不足 4 位直接处理),每 2 位做一位,前面加上%,编码成%XY 格式。

可以看到,+被编码成为了%2B

解码的规则就是编码规则的逆向。

编码和解码


3、HTTP请求和响应报头格式

3.1、请求报头

从上图可以看出,请求报头涵盖请求行、请求报头、空行和请求正文。

  • 请求行:[方法] + [url] + [版本]

  • 请求报头:请求的属性,冒号分割的键值对,每组属性之间使用\r\n分隔,遇到空行表示当前请求报头部分结束。

  • 正文:空行后面的内容都是正文,正文允许为空字符串。如果正文存在,则在请求行会有一个Conten-Length属性的字段来标识正文的长度。

代码显示请求报头字段:


3.2、响应报头

从上图可以看出,请求报头涵盖状态行、响应报头、空行和响应正文。

  • 状态行:[版本号] + [状态码] + [状态码解释]

  • 响应报头:响应的属性,冒号分割的键值对,每组属性之间使用\r\n分隔,遇到空行表示当前响应报头部分结束

  • 正文:空行后面的内容都是正文。正文允许为空字符串,如果正文存在,则在正文中会有一个Content-Length属性来标识 正文的长度,如果服务器返回了一个 html 页面,那么 html 页面内容就是在正文中。

程序显示响应报头字段:注意,这里没有打印正文部分,因为当以二进制格式打开文件的时候,正文部分拿到是二进制,显示的字符我们看不懂。这里选择不打印。


4、HTTP的方法

HTTP 方法描述
GET请求指定的资源。仅用于请求数据,不对资源进行修改。
POST向服务器提交数据进行处理(例如提交表单或者上传文件)。数据包含在请求体中。
PUT请求服务器存储一个资源,并用请求体中的数据替代指定的资源(完全替代)。
DELETE请求服务器删除指定的资源。
HEAD类似于GET请求,只不过返回的响应中没有具体内容,用于获取报头。
OPTIONS返回服务器支持的HTTP方法。可以用于检查服务器的功能。
PATCH用于局部更新资源。只传递需要修改的数据,而不是整个资源。
CONNECT建立一个到目标资源的隧道。主要用于代理服务器将HTTPS请求传到目的服务器。
TRACE回显服务器收到的请求,主要用于测试或诊断。

常用的方法是:GET和POST


4.1、GET方法

用途:用于请求 URL 指定的资源。

示例:GET /index.html HTTP/1.1

特性:指定资源经服务器端解析后返回响应内容。

form 表单:https://www.runoob.com/html/html-forms.html

这里的method方法的post改为get(大小写忽略),就是请求时用的GET方法。

GET方法如果在提交时,有参数需要提交的话,会把参数放在url中

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>About Us</title>
</head>

<body>
<header>
  <h1>About Us</h1>
  <nav>
      <ul>
          <li><a href="index.html">Home</a></li>
          <li><a href="about.html">About</a></li>
          <li><a href="contact.html">Contact</a></li>
      </ul>
  </nav>
</header>
<!-- get把账号密码放url,post放正文 -->
<form action="/login" method="get" 
  <label for="username">用户名:</label><br>
  <input type="text" id="username" name="username" required><br><br>

  <label for="password">密码:</label><br>
  <input type="password" id="password" name="password" required><br><br>

  <input type="submit" value="提交">
</form>
<main>
  <section>
      <h2>Our Story</h2>
      <p>We are a company dedicated to providing the best service possible. Our journey started in...</p>
  </section>
  <section>
      <h2>Our Team</h2>
      <p>Meet the wonderful people behind our success...</p>
  </section>
</main>
<footer>
  <p>&copy; 2024 Your Name. All rights reserved.</p>
</footer>
<img src="/Image/2.png" alt="test">
</body>

</html>

Fiddler抓包:可以看到账号密码是在url中。


4.2、POST方法

用途:用于传输实体的主体,通常用于提交表单数据。

示例:GET /index.html HTTP/1.1

特性:可以发送大量的数据给服务器,并且数据包含在请求体中。

form 表单:https://www.runoob.com/html/html-forms

POST方法如果在提交时,有参数需要提交的话,会把参数放在正文中

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>About Us</title>
</head>

<body>
<header>
  <h1>About Us</h1>
  <nav>
      <ul>
          <li><a href="index.html">Home</a></li>
          <li><a href="about.html">About</a></li>
          <li><a href="contact.html">Contact</a></li>
      </ul>
  </nav>
</header>
<!-- get把账号密码放url,post放正文 -->
<form action="/login" method="post" 
  <label for="username">用户名:</label><br>
  <input type="text" id="username" name="username" required><br><br>

  <label for="password">密码:</label><br>
  <input type="password" id="password" name="password" required><br><br>

  <input type="submit" value="提交">
</form>
<main>
  <section>
      <h2>Our Story</h2>
      <p>We are a company dedicated to providing the best service possible. Our journey started in...</p>
  </section>
  <section>
      <h2>Our Team</h2>
      <p>Meet the wonderful people behind our success...</p>
  </section>
</main>
<footer>
  <p>&copy; 2024 Your Name. All rights reserved.</p>
</footer>
<img src="/Image/2.png" alt="test">
</body>

</html>

Fiddler抓包:可以看到账号密码(提交的参数)在正文部分!


4.3、HEAD方法

用途:与 GET 方法类似,但不返回报文主体部分,仅返回响应头。

示例:HEAD /index.html HTTP/1.1

特性:用于确认 URL 的有效性及资源更新的日期时间等。

预备知识:curl 是一个命令行工具,用于传输数据,支持多种协议,包括 HTTP、HTTPS、FTP 等。它常用于测试或自动化脚本中,以发送请求到服务器并接收响应。当你使用 curl -i www.baidu.com 命令时,你实际上是在尝试通过 HTTP 协议向 www.baidu.com 发送一个 GET 请求,并希望获取响应的头部信息(headers)以及可能的响应体(body)。--head就是只获取响应头,-i就是--include默认情况下(不加选项),curl 只显示响应体,不包括头部。

xp2@VM-8-12-ubuntu:~$ curl --head  www.baidu.com
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: keep-alive
Content-Length: 277
Content-Type: text/html
Date: Thu, 08 Aug 2024 03:04:49 GMT
Etag: "575e1f71-115"
Last-Modified: Mon, 13 Jun 2016 02:50:25 GMT
Pragma: no-cache
Server: bfe/1.0.8.18

xp2@VM-8-12-ubuntu:~$ 

5、HTTP状态码

状态码原因短语类别
1XX接收的请求正在处理Informational (信息性状态码)
2XX请求正常处理完毕Success (成功状态码)
3XX需要进行附加操作以完成请求Redirection (重定向状态码)
4XX服务器无法处理请求Client Error (客户端错误状态码)
5XX服务器处理请求出错Server Error (服务器错误状态码)

常见的状态码及含义描述:

状态码含义应用样例
100Continue上传大文件时,服务器告诉客户端可以继续上传
101Switching Protocols服务器同意客户端更改协议
200OK访问网站首页,服务器返回网页内容
201Created发布新文章,服务器返回文章创建成功的信息
202Accepted服务器已接受请求,但尚未处理
203Non-Authoritative Information服务器已成功处理请求,但返回的信息可能来自另一来源
204No Content删除文章后,服务器返回“无内容”表示操作成功
205Reset Content服务器处理成功,用户代理应重置文档视图
206Partial Content服务器成功处理了部分 GET 请求
300Multiple Choices多种选择,用户或用户代理可以自行选择
301Moved Permanently网站换域名后,自动跳转到新域名;搜索引擎更新新网站链接时使用
302Found临时重定向,要求客户端执行临时重定向
303See Other客户端应使用 GET 方法获取资源
304Not Modified缓存的资源未修改,客户端可继续使用
305Use Proxy资源必须通过代理访问
307Temporary Redirect临时重定向,要求客户端保持请求方法和主体
400Bad Request请求语法错误,服务器无法理解
401Unauthorized请求要求用户身份验证
403Forbidden服务器理解请求,但拒绝执行
404Not Found服务器找不到请求的资源
405Method Not Allowed请求方法不被允许
406Not Acceptable服务器无法根据客户端请求的内容特性完成请求
407Proxy Authentication Required请求要求代理身份验证
408Request Timeout服务器等待客户端发送的请求时间过长
409Conflict服务器在完成请求时发生冲突
410Gone请求的资源已被永久删除
411Length Required服务器要求在请求中包含内容长度
412Precondition Failed服务器未满足请求的前提条件
413Payload Too Large请求实体过大,服务器无法处理
414URI Too Long请求的 URI 过长,服务器无法处理
415Unsupported Media Type请求的媒体格式不受支持
416Range Not Satisfiable请求的范围无法满足
417Expectation Failed服务器未满足 “Expect” 请求标头字段的要求
500Internal Server Error服务器内部错误
501Not Implemented服务器不支持请求的方法
502Bad Gateway服务器作为网关或代理时收到无效响应
503Service Unavailable服务器目前无法处理请求(由于超载或停机维护)
504Gateway Timeout服务器作为网关或代理,未及时从上游服务器收到响应
505HTTP Version Not Supported服务器不支持请求的 HTTP 版本

关于重定向:

HTTP 状态码 301(永久重定向)和 302(临时重定向)都依赖 Location 选项。以下是关于两者依赖 Location 选项的详细说明:

HTTP 状态码 301(永久重定向)

当服务器返回 HTTP 301 状态码时,表示请求的资源已经被永久移动到新的位置

在这种情况下,服务器会在响应中添加一个 Location 头部,用于指定资源的新位置。这个 Location 头部包含了新的 URL 地址,浏览器会自动重定向到该地址。

例如,在 HTTP 响应中,可能会看到类似于以下的头部信息:

HTTP/1.0 301 Moved Permanently: This and all future requests should be directed to the given URI.
Connection: keep-alive
Content-Type: 
Keep-Alive: timeout=4
Location: http://129.204.171.204:8888/Image/2.png
Proxy-Connection: keep-alive


HTTP 状态码 302(临时重定向)

当服务器返回 HTTP 302 状态码时,表示请求的资源临时被移动到新的位置

同样地,服务器也会在响应中添加一个 Location 头部来指定资源的新位置。浏览器会暂时使用新的 URL 进行后续的请求,但不会缓存这个重定向。

例如,在 HTTP 响应中,可能会看到类似于以下的头部信息:

HTTP/1.0 302 Found: Tells the client to look at (browse to) another URL.
Connection: keep-alive
Content-Type: 
Keep-Alive: timeout=4
Location: http://129.204.171.204:8888/Image/2.png
Proxy-Connection: keep-alive


总结:无论是 HTTP 301 还是 HTTP 302 重定向,都需要依赖 Location 选项来指定资源的新位置。这个 Location 选项是一个标准的 HTTP 响应头部,用于告诉浏览器应该将请求重定向到哪个新的 URL 地址。


6、HTTP常见报头类型

字段名含义样例
Content-Type资源的MIME类型(例如,文本、HTML、JPEG图片等)Content-Type: text/html; charset=utf-8
Content-Length请求体(body)的字节大小Content-Length: 348
User-Agent发起请求的客户端(如浏览器)信息User-Agent: Mozilla/5.0 (Windows NT 10.0; ...)
Accept客户端可接受的响应内容类型(如HTML、JSON等)Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Authorization客户端身份验证信息(如Basic认证或Token)Authorization: Basic QWxhZGRpbjpvcGVuU2VzYW1l
Cookie存储在客户端的键值对数据,服务器可用于追踪用户会话等Cookie: sessionToken=abc123; user=johndoe
Set-Cookie服务器发送到客户端的Cookie信息,用于创建或更新CookieSet-Cookie: sessionToken=abc123; Path=/; HttpOnly
Cache-Control指示请求/响应消息体是否应被缓存、何时可以缓存等策略Cache-Control: max-age=600, public
Location重定向的目标URL(主要用于3xx响应)Location: http://example.com/new-page.html
Referer指示当前请求页面的前一个页面的URL(如果存在)Referer: http://example.com/some-page.html
Connection指示是否需要保持连接(keep-alive)或关闭(close)Connection: keep-alive
Host请求的资源所在的服务器主机名和端口号(如果非标准端口)Host: www.example.com
Date消息发送的日期和时间(RFC 7231 格式)Date: Tue, 15 Nov 1994 08:12:31 GMT
Content-Encoding对实体主体内容采用的编码类型(如gzip、deflate等)Content-Encoding: gzip
Server处理请求的服务器软件名称和版本号(如Apache/2.4.41)Server: Apache/2.4.41 (Unix)

7、简单的HTTP服务器

下面代码基本融合了上面所有所涉及的核心知识。

因为代码里面存在相对路径,还有文件夹,防止路径错误请自行下载,代码放在这里了:HTTP服务器

运行结果:


OKOK,应用层HTTP协议就到这里,如果你对Linux和C++也感兴趣的话,可以看看我的主页哦。下面是我的github主页,里面记录了我的学习代码和leetcode的一些题的题解,有兴趣的可以看看。

Xpccccc的github主页

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Xpccccc

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

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

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

打赏作者

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

抵扣说明:

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

余额充值