【网络】HTTP协议详解

news/2024/5/15 1:35:14/文章来源:https://blog.csdn.net/baichendada/article/details/126925361

😀大家好,我是白晨,一个不是很能熬夜😫,但是也想日更的人✈。如果喜欢这篇文章,点个赞👍,关注一下👀白晨吧!你的支持就是我最大的动力!💪💪💪

在这里插入图片描述

文章目录

  • 📙前言
  • 📗HTTP协议
    • 🏡1. HTTP背景介绍
    • ⛪2. HTTP知识预备
      • 2.1 TCP/IP协议
      • 2.2 URI 和 URL
      • 2.3 DNS服务
    • 🕋3. HTTP协议格式
      • 请求报文
      • 响应报文
    • 🕌4. HTTP的方法
      • GET:获取资源
      • POST:传输实体主体
      • PUT:传输文件
      • HEAD:获得报文首部
      • DELETE:删除文件
      • OPTIONS:询问支持的方法
      • TRACE:追踪路径
      • CONNECT:要求用隧道协议连接代理
    • 🛕5. HTTP的状态码
      • 5.1 状态码分类
      • 5.2 2XX 成功
        • 200 OK
        • 204 No Content
        • 206 Partial Content
      • 5.3 3XX 重定向
        • 301 Moved Permanently
        • 302 Found
        • 303 See Other
        • 304 Not Modified
        • 307 Temporary Redirect
      • 5.4 4XX 客户端错误
        • 400 Bad Request
        • 401 Unauthorized
        • 403 Forbidden
        • 404 Not Found
      • 5.5 5XX服务器错误
        • 500 Internal Server Error
        • 503 Service Unavailable
    • 🕍6. HTTP的首部
      • HTTP 首部字段分类
      • HTTP 首部字段结构
      • HTTP 首部字段类型
      • HTTP 首部字段概览
        • Connection
        • Cookie
        • Session
    • ⛩️7. 搭建简易HTTP服务器
  • 📕后记

📙前言


哟,大家好,我是白晨。距离上一次更新已经过了一段时间了,属实是当鸽子当惯了🤣。

上一篇文章我们全面讲解了网络中的基础知识(没看过上篇文章的的可以先去看上一篇文章【网络】网络基础知识详解),这篇文章白晨准备从应用层中的一个及其重要的协议开始讲起,它就是——HTTP协议。HTTP协议由于简单、快速而成为了应用最广泛的web文档传递协议协议,在理解了HTTP协议的种种行为后,再自顶向下去学习传输层,网络层以及数据链路层将会好理解许多。


📗HTTP协议


🏡1. HTTP背景介绍


1989 年 3 月,HTTP 诞生。最初设想的基本理念是: 借助多文档之间相互关联形成的超文本(HyperText),连成可相互参阅的 WWW( World Wide Web,万维网)。现在已提出了 3 项 WWW 构建技术,分别是:

  • 把 SGML(StandardGeneralized Markup Language,标准通用标记语言)作为页面的文本标记语言的 HTML(HyperText Markup Language,超文本标记语言);
  • 作为文档传递协议的 HTTP ;
  • 指定文档所在地址的 URL(Uniform Resource Locator,统一资源定位符)。

WWW 这一名称, 是 Web 浏览器当年用来浏览超文本的客户端应用程序时的名称。现在则用来表示这一系列的集合,也可简称为 Web。


⛪2. HTTP知识预备


2.1 TCP/IP协议

在这里插入图片描述

上篇文章我们曾经讲过,TCP/IP模型将网络分为了四层,将不同的任务划分,每层只要完成自己的任务即可,完成了每层间的解耦,同时上层依赖下层的服务以实现自己的功能。HTTP是一个建立在TCP/IP协议族上的应用层协议,所以,要利用HTTP发送数据,就要通过上图过程。

我们用 HTTP 举例来说明,

  • 首先作为发送端的客户端在应用层(HTTP 协议)发出一个想看某个 Web 页面的 HTTP 请求。
  • 接着,为了传输方便,在传输层(TCP 协议)把从应用层处收到的数据(HTTP 请求报文)进行分割,并在各个报文上打上标记序号及端口号后转发给网络层。
  • 在网络层(IP 协议),增加作为通信目的地的 MAC 地址后转发给链路层。这样一来,发往网络的通信请求就准备齐全了。
  • 接收端的服务器在链路层接收到数据, 按序往上层发送,一直到应用层。当传输到应用层,才能算真正接收到由客户端发送过来的 HTTP。

在这里插入图片描述

2.2 URI 和 URL

URL (Uniform Resource Locator) ,我们称为统一资源定位符。它是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。也就是我们经常说的网址。

  • 具体格式为:

在这里插入图片描述

URI (Uniform Resource Identifier) ,我们称为统一资源标识符 。URI 就是由某个协议方案表示的资源的定位标识符。

  • URI 与 URL 的联系:

URI 用字符串标识某一互联网资源, 而 URL 表示资源的地点(互联网上所处的位置),可见 URL 是 URI 的子集URI 可以分为 URL + URN (统一资源名称) ,打个比方,URI 相当于一个人,URL 就是这个人的住址,URN 就是这个人的名字。

所以,URL 必定也是 URI

  • URI 与 URL 的区别:

URI 不一定是 URL,根据上文,URI 中还有一个 URN ,它只是命名资源,而不定位资源。

2.3 DNS服务

DNS( Domain Name System)**DNS 协议提供通过域名查找 IP 地址,或逆向从 IP 地址反查域名的服务 **,和 HTTP 协议一样位于应用层的协议。

相比IP地址这种纯数字,域名这种字母+数字的组合让人更加容易记忆,比如:百度的IP地址为110.242.68.3 ,域名为www.baicdu.com。可见,大多数用户在访问网站时,都习惯使用域名。

但我们知道在网络上,IP地址+端口号才能定位一个唯一的服务,所以就需要 DNS服务 将域名解析为 IP地址。

具体工作场景如下图:

在这里插入图片描述


🕋3. HTTP协议格式


请求报文

POST /data/index HTTP/1.1
Host: baichen.com
Connection: keep-alive
Content-Type: text/html; charset=utf8
Content-Length: 16name=chen&age=37

请求报文的构成为:

在这里插入图片描述

由此,我们可以得到请求报文的格式为:

  • 请求行: 方法 + URL + 协议版本

  • 请求头部: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔。

  • 空行:空行用于标识请求头部结束,请求正文开始。

  • 请求正文: 空行后面的内容都是请求正文,内容为应发送的数据。请求正文允许为空字符串。如果请求正文存在, 则在请求头部中会有一个Content-Length属性来标识请求正文的长度。

在这里插入图片描述

这里要解释一个问题,为什么前文讲解URL的结构这么复杂,但是在上面的请求报文中却好像只有目录结构,而没有协议、域名等部分?

当客户端请求访问资源而发送请求时, URL 需要将作为请求报文中的请求 URL 包含在内。指定请求 URI 的方式有很多。

  • 指定完整的URL
GET http://www.baichen.com/index.html HTTP/1.1
  • 在首部字段Host中写明网络域名或IP地址
GET / HTTP/1.1
Host: www.baichen.comHTTP请求的'/'并不是根目录,而是web根目录,意味着我们要请求该网站的首页
  • 对于针对服务器本身的访问,可以用* 来代替请求 URL
OPTIONS * HTTP/1.1 -- 查询服务器支持的方法

响应报文

HTTP/1.1 200 OK
Date: Tue, 10 Jul 2012 06:50:15 GMT
Content-Length: 362
Content-Type: text/html<html>
…

响应报文的构成为:

在这里插入图片描述

由此,我们可以得到响应报文的格式为:

  • 相应行: 协议版本 + 状态码 + 状态码描述
  • 响应头部: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔。
  • 空行:空行用于标识响应头部结束,响应正文开始。
  • 响应正文: 空行后面的内容都是响应正文,内容为应发送的数据。响应正文允许为空字符串。如果响应正文存在,则在响应头部中会有一个Content-Length属性来标识响应正文的长度;如果服务器返回了一个html页面,那么html页面内容就是在响应正文中。

在这里插入图片描述


🕌4. HTTP的方法


向请求 URL 指定的资源发送请求报文时,采用称为方法的命令。方法的作用在于, 可以指定请求的资源按期望产生某种行为。方法中有 GETPOSTHEAD 等。

eg.

在这里插入图片描述

  • HTTP支持的方法详见下表:
方法说明支持的HTTP协议版本
GET获取资源1.0、1.1
POST传输实体主体1.0、1.1
PUT传输文件1.0、1.1
HEAD获得报文首部1.0、1.1
DELETE删除文件1.0、1.1
OPTIONS询问支持方法1.1
TRACE追踪路径1.1
CONNECT要求用隧道协议连接代理1.1
LINK建立和资源之间的联系1.0
UNLINE断开连接关系1.0

LINK 和 UNLINK 方法已经被 HTTP/1.1 弃用,这两个方法只需了解即可。

GET:获取资源

GET 方法用来请求访问已被 URL 识别的资源。指定的资源经服务器端解析后返回响应内容。

请求报文:
GET / HTTP/1.1
Host: www.baichen.com
Connection: keep-alive
User-Agent: XXXXX响应报文:
HTTP/1.1 200 OK
Content-Type: text/plainhello, i'm from the futurn

上面就是一个经典的使用GET方法的例子,GET方法是一个使用非常频繁的方法,用于获取指定 URL 的资源,当我们访问一个网站的时候,第一次使用的方法基本都是GET,以获取网页信息。

POST:传输实体主体

POST 方法用来传输实体的主体。虽然用 GET 方法也可以传输实体的主体,但一般不用 GET 方法进行传输,而是用 POST 方法。虽说 POST 的功能与 GET 很相似,但POST 的主要目的并不是获取响应的主体内容。

:使用GET方法传输的内容直接会在URL上显示,而用POST方法传输的内容会在报文正文传输,而不会在URL上直接显示。

POST / HTTP/1.1
Host: www.baichen.com
Content-Length: 1560(1560字节的数据)

PUT:传输文件

PUT 方法用来传输文件。就像 FTP 协议的文件上传一样,要求在请求报文的主体中包含文件内容,然后保存到请求 URL 指定的位置。 这个方法由于安全性较低,所以大部分主流网站不会支持这个方法或者配合验证机制使用此方法。

PUT / HTTP/1.1
Host: www.baichen.com
Content-Type: text/html
Content-Length: 1560(1560字节的数据)

HEAD:获得报文首部

HEAD 方法和 GET 方法一样,只是不返回报文主体部分,用于确认 URL 的有效性及资源更新的日期时间等。

HEAD /index.html HTTP/1.1
Host: www.baichen.com

DELETE:删除文件

DELETE 方法按请求 URL 删除指定的资源。DELETE 方法和 PUT 效果正好相反,所以 DELETE 也具有安全性问题,一般不会单独使用。

DELETE /index.html HTTP/1.1
Host: www.baichen.com

OPTIONS:询问支持的方法

OPTIONS 方法用来查询针对请求 URL 指定的资源支持的方法。

请求:
OPTIONS * HTTP/1.1
Host: www.baichen.com返回:
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
(返回服务器支持的方法)

TRACE:追踪路径

TRACE 方法是让 Web 服务器端将之前的请求通信环回给客户端的方法 .客户端通过 TRACE 方法可以查询发送出去的请求是怎样被加工修改 / 篡改的。这是因为,请求想要连接到源目标服务器可能会通过代理中转, TRACE 方法就是用来确认连接过程中发生的一系列操作。

发送请求时, 在 Max-Forwards 首部字段中填入数值,每经过一个服务器端就将该数字减 1, 当数值刚好减到 0 时,就停止继续传输,最后接收到请求的服务器端则返回状态码 200 OK 的响应

请求:
TRACE / HTTP/1.1
Host: WWW.baichen.com
Max-Forwards: 2返回:
HTTP/1.1 200 OK
Content-Type: message/http
Content-Length: 1024TRACE / HTTP/1.1
Host: www.baichen.com
Max-Forwards: 2(返回响应包含请求内容)

CONNECT:要求用隧道协议连接代理

CONNECT 方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行 TCP 通信。

使用隧道通信相当于是在客户端和服务器之间建立了一个隧道,两者的报文从隧道走,可以保证通信的连续和安全。

CONNECT方法使用格式:
CONNECT 代理服务器名:端口号 HTTP版本eg.
CONNECT 101.58.2.1:8080 HTTP/1.1
Host: www.baichen.com

🛕5. HTTP的状态码


状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果。 借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了错误。

eg.

在这里插入图片描述

5.1 状态码分类


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

RFC2016上规定的状态码有40余种,再加上WebDAV等的状态码,一共有60余种。但是,常用的状态码大概就14种,下面由我向大家介绍这14种状态码。


5.2 2XX 成功


2XX 的响应结果表明请求被正常处理了。

200 OK

表示从客户端发来的请求在服务器端被正常处理了。

204 No Content

该状态码代表服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分。 另外,也不允许返回任何实体的主体。比如,当从浏览器发出请求处理后, 返回 204 响应,那么浏览器显示的页面不发生更新 。

206 Partial Content

该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的 GET 请求。响应报文中包含由 Content-Range 首部字段指定范围的实体内容。


5.3 3XX 重定向


3XX 响应结果表明浏览器需要执行某些特殊的处理以正确处理请求。

301 Moved Permanently

永久性重定向。该状态码表示请求的资源已被分配了新的 URL,以后应使用资源现在所指的 URL。也就是说,如果已经把资源对应的 URL 保存为书签了,这时应该按 Location 首部字段提示的 URL 重新保存。

永久性重定向一般用于网址搬迁、网站升级等服务,需要用 Location: 新的地址 指明跳转的地址,301状态码会建议浏览器更新书签,将其指向新网址,但是浏览器的实现各不相同,可能需要你手动修改,也可能帮你修改。

302 Found

临时性重定向。该状态码表示请求的资源已被分配了新的 URL,希望用户(本次)能使用新的 URL 访问。

一般用于网站抢修,或者跳转至登录页面等,这个状态码也需要配合 Location: 新的地址 一起使用,这个状态码不会建议浏览器更新书签。

303 See Other

该状态码表示由于请求对应的资源存在着另一个 URI,应使用 GET 方法定向获取请求的资源。
303 状态码和 302 Found 状态码有着相同的功能,但 303 状态码明确表示客户端应当采用 GET 方法获取资源,这点与 302 状态码有区别。

:当 301、302、303 响应状态码返回时,几乎所有的浏览器都会把 POST 改成 GET,并删除请求报文内的主体,之后请求会自动再次发送。301、302 标准是禁止将 POST 方法改变成 GET 方法的,但实际使用时大家都会这么做。

304 Not Modified

该状态码表示客户端发送附带条件的请求 A 时,服务器端允许请求访问资源,但未满足条件的情况。 304 状态码返回时,不包含任何响应的主体部分。

307 Temporary Redirect

临时重定向。该状态码与 302 Found 有着相同的含义。尽管 302 标准禁止 POST 变换成 GET,但实际使用时大家并不遵守。

307 会遵照浏览器标准, 不会从 POST 变成 GET。但是,对于处理响应时的行为,每种浏览器有可能出现不同的情况。


5.4 4XX 客户端错误


4XX 的响应结果表明客户端是发生错误的原因所在。

400 Bad Request

该状态码表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。另外,浏览器会像 200 OK 一样对待该状态码。

401 Unauthorized

该状态码表示发送的请求需要有通过 HTTP 认证( BASIC 认证、DIGEST 认证)的认证信息。 另外若之前已进行过 1 次请求,则表示用户认证失败。

返回含有 401 的响应必须包含一个适用于被请求资源的 WWW-Authenticate 首部用以质询( challenge)用户信息。当浏览器初次接收到 401 响应,会弹出认证用的对话窗口。

403 Forbidden

该状态码表明对请求资源的访问被服务器拒绝了。服务器端没有必要给出拒绝的详细理由, 但如果想作说明的话,可以在实体的主体部分对原因进行描述,这样就能让用户看到了。

未获得文件系统的访问授权, 访问权限出现某些问题(从未授权的发送源 IP 地址试图访问)等列举的情况都可能是发生 403 的原因。

404 Not Found

该状态码表明服务器上无法找到请求的资源。除此之外,也可以在服务器端拒绝请求且不想说明理由时使用。


5.5 5XX服务器错误


5XX 的响应结果表明服务器本身发生错误。

500 Internal Server Error

该状态码表明服务器端在执行请求时发生了错误。

503 Service Unavailable

该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。 如果事先得知解除以上状况需要的时间,最好写入 Retry After 首部字段再返回给客户端。


状态码的本意是用来快速获取请求状态,但是在很多场景下,我们会发现状态码和出错的地方根本就对不上。归根到底,状态码并不是一种强制性的命令,而是一种建议式的反馈,很多浏览器对于同一状态码的处理可能都千差万别,比如,404 状态码在谷歌浏览器上,如果返回有实体主体,那么谷歌浏览器并不会理会 404 状态码,而是显示返回的实体主体的内容,但是404 状态码在Edge浏览器上就会强制执行 404 Not Fount。

虽然网络上的状态码鱼龙混杂,但是我们自己写的状态码一定要符合标准,这样有利于养成良好的代码习惯和排查错误。


🕍6. HTTP的首部


  • HTTP 协议的请求和响应报文中必定包含 HTTP 首部。首部内容为客户端和服务器分别处理请求和响应提供所需要的信息。

  • HTTP 首部字段是构成 HTTP 报文的要素之一。在客户端与服务器之间以 HTTP 协议进行通信的过程中,无论是请求还是响应都会使用首部字段,它能起到传递额外重要信息的作用。使用首部字段是为了给浏览器和服务器提供报文主体大小、 所使用的语言、认证信息等内容。

eg.

在这里插入图片描述

HTTP 首部字段分类

  • 请求报文

在这里插入图片描述

  • 响应报文

在这里插入图片描述

HTTP 首部字段结构

首部字段名: 字段值
eg.
Content-Type: text/plain, charset=utf-8  -- 报文主体的对象类型,字体协议为utf-8协议

HTTP 首部字段类型

  • 请求首部字段
  • 响应首部字段
  • 通用首部字段
  • 实体首部字段

HTTP 首部字段概览

  • 通用首部字段

在这里插入图片描述

  • 请求首部字段

在这里插入图片描述

  • 响应首部字段

在这里插入图片描述

  • 实体首部字段

在这里插入图片描述

Connection

HTTP/1.1 之前的 HTTP 版本的默认连接都是非持久连接,也叫短连接。HTTP 协议是基于 TCP 协议的,所以要进行一次会话必须要经过建立连接、请求、响应、断开连接的过程,这样每进行一次请求和响应都要建立连接和断开连接,非常耗费时间,这是由于以前传输的都是体积不太大文本等文件,不需要持久连接。但是,现在由于网络传输需求的迅速发展,持久连接已经成为了 HTTP 连接的必然。

为此,如果想在旧版本的 HTTP 协议上维持持续连接,则需要指定 Connection 首部字段的值为 Keep-Alive

Connection: Keep-Alive

HTTP/1.1 版本的默认连接都是持久连接,也叫长连接。为此,客户端会在持久连接上连续发送请求。 当服务器端想明确断开连接时, 则指定
Connection 首部字段的值为 Close。

Connection: Close

Connection 字段还有控制不再转发给代理的首部字段的功能,但是这里主要是讲解长短连接的概念

Cookie

Cookie 的工作机制是用户识别及状态管理。 Web 网站为了管理用户的状态会通过 Web 浏览器,把一些数据临时写入用户的计算机内。接着当用户访问该Web网站时,可通过通信方式取回之前发放的Cookie。

Cookie其实是一种特别我们经常使用的字段,因为HTTP协议是一种无状态的协议,也就意味着:本次会话和上一次会话之间没有任何关系,互不影响。但是,我们日常使用B站等视频网站时,却能够保持登录状态,这是因为HTTP协议不是无状态的吗?

当然不是,HTTP协议引入了 Cookie 值作为“会话保持”的媒介,那么 cookie 到底是什么呢?

在这里插入图片描述

简单来说,Cookie 是一种保存在内存或者本地磁盘上的数据文件,其中保存着客户端的各种信息。

  • Set-Cookie

服务器准备开始管理客户端的状态时,会使用 Set-Cookie 字段事先设置客户端Cookie

Set-Cookie 字段的属性:

属性说明
NAME=VALUE赋予Cookie的名称和其值(必需项)
expires=DATECookie的有效期(若不明确指定则默认为浏览器关闭前为止)
path=PATH将服务器上的文件目录作为Cookie的适用对象(若不指定则 默认为文档所在的文件目录)
domain=域名作为Cookie适用对象的域名 (若不指定则默认为创建 Cookie 的服务器的域名)
Secure仅在HTTPS安全通信时才会发送Cookie
HttpOnly加以限制,使Cookie不能被JavaScript脚本访问

eg.

Set-Cookie: id=1; password=123456; expires=Tue, 05 Jul 2023 18:43:32 GMT; path=/; domain=baichen.com;
  • Cookie

当被服务器用 Set-Cookie 设置了 Cookie 以后,客户端发送请求报文时,会在头部字段添加一个 Cookie 字段,用来保存服务器设置的 Cookie 。接收到多个 Cookie 时,同样可以以多个 Cookie 形式发送。

一般来说,每个Cookie 的大小不能超过 4KB

eg.

Cookie: id=1; password=123456;
  • Set-Cookie 和 Cookie 实例

本会话的源代码见简易HTTP服务器,以下报文都是基于下文代码获得,大家可以自行验证。

请求:
GET / HTTP/1.1
Host: baichen.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: xxx
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
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6响应:
HTTP/1.0 200 OK
Set-Cookie: id=1111       -- 设置Cookie
Set-Cookie: password=2222 -- 设置Cookie
Content-Type: text/html, charset=utf-8
Content-Length: XXX.....请求:
POST / HTTP/1.1
Host: baichen.com
Connection: keep-alive
Content-Length: 37
Content-Type: application/x-www-form-urlencoded
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
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: id=1111; password=2222 --- Cookie值name=%E7%99%BD%E6%99%A8&passwd=123456

Session

如果有人通过一些手段截取了我们的 Cookie 文件,如果Cookie使用的是明文传递,那么我们的账号、密码等个人信息会被窃取,如果Cookie使用的是加密传递,虽然攻击者不能获得我们的私密信息,但是他可以使用我们的Cookie访问各种私密资源,甚至做违法之事。当然,前文提到了Cookie在配置良好的情况下,安全性还不错,但是总有被劫持的风险。

Session 就是为了解决上述问题而设计的方案,具体做法是:存储于服务器上的 Session 对象存储特定用户会话所需的属性及配置等私密信息,第一次访问该服务器的用户会创建一个唯一的 Session 对象存储私密信息,以后访问该服务器时就根据用户信息读取对应的信息。

由于 Session 对象存储在服务器上,不在客户端本地保存,所以不会被劫持,这样就解决了安全的问题。但是可以只使用 Session 方案吗?是不行的,Session 是需要消耗服务器服务器资源的,会增加运行成本,所以并不能将大规模数据都保存到 Session 对象中。一般的方案是:Cookie 和 Session 配合使用,以达到安全和会话保持的平衡。

  • Cookie 和 Session 对比
    1. Cookie 数据存放在客户端上,Session 数据放在服务器上。
    2. Cookie不是很安全,别人可以分析存放在本地的 Cookie 并进行 Cookie 欺骗。
    3. Session 对比 Cookie 来说更安全,Session 会在一定时间内保存在服务器上,但是当访问增多,会比较占用服务器的性能。
    4. 一般的方案是:CookieSession 配合使用,以达到安全和会话保持的平衡。

⛩️7. 搭建简易HTTP服务器


这次实现的HTTP服务器是一个最简单的HTTP服务器,主要是为了让大家了解HTTP的使用,实现的功能有显示网页,上传数据,设置Cookie等。

  • 效果图如下:
    在这里插入图片描述

  • 首先,封装一个套接字库。
#pragma once#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>class Sock
{
public:static int Socket(){int sock = socket(AF_INET, SOCK_STREAM, 0);if(sock < 0){std::cerr << "socket failed" << std::endl;exit(1);}}static void Bind(int sock, uint16_t port){struct sockaddr_in local;local.sin_family = AF_INET;local.sin_port = htons(port);local.sin_addr.s_addr = INADDR_ANY;if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){std::cerr << "bind failed" << std::endl;exit(2);}}static void Listen(int sock){const int backlog = 5;if(listen(sock, backlog) < 0){std::cerr << "listen failed" << std::endl;exit(3);}}// tcp通信直接在套接字中写就可以,所以可以不用返回客户端的信息static int Accept(int sock){struct sockaddr_in peer;socklen_t len = sizeof(peer);int new_sock = accept(sock, (struct sockaddr*)&peer, &len);if(new_sock < 0){std::cerr << "accept failed" << std::endl;exit(4);}return new_sock;}static void Connect(int sock, const std::string& ip, uint16_t port){struct sockaddr_in server;memset((void*)&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(port);server.sin_addr.s_addr = inet_addr(ip.c_str());if(connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0){std::cerr << "connect failed" << std::endl;exit(5);}else{std::cout << "connect succeed" << std::endl;}}
};
  • HTTP服务:
#include "Sock.hpp"
#include <fstream>
#include <sys/stat.h>// 设置网页根目录
#define WWWROOT "./wwwroot/"
#define HOME_PAGE "index.html"void Usage(std::string args)
{std::cout << "Usage : " << args << " server_port" << std::endl;
}void *handler(void *args)
{pthread_detach(pthread_self());int sock = *(int *)args;delete (int *)args;#define NUM 1024 * 10char buf[NUM];memset(buf, 0, sizeof(NUM));// 接收请求报文ssize_t sz = recv(sock, buf, sizeof(buf) - 1, 0);if (sz > 0){buf[sz] = 0;std::cout << buf << std::endl;std::string fileloc = WWWROOT;fileloc += HOME_PAGE;// fileloc += "a/b";// 读取网页信息std::ifstream ifs(fileloc);if (!ifs.is_open()){std::string http_response = "HTTP/1.0 404 NotFount";http_response += "Content-Type: text/html, charset=utf-8";http_response += "\n";http_response += "<html><p> 你访问的资源不存在 </p></html>";send(sock, http_response.c_str(), http_response.size(), 0);}else{// 构建响应报文std::string line;std::string echo;while (std::getline(ifs, line)){echo += line;}struct stat fst;stat(fileloc.c_str(), &fst);std::string http_response = "HTTP/1.0 200 OK\n";// std::string http_response = "HTTP/1.0 404 NotFount";// std::string http_response = "HTTP/1.0 302 Temporarily Move\n";// http_response += "Location: http://www.bilibili.com";http_response += "Set-Cookie: id=1111\n";http_response += "Set-Cookie: password=2222\n";http_response += "Content-Type: text/html, charset=utf-8\n";http_response += "Content-Length: ";http_response += std::to_string(fst.st_size);http_response += "\n\n";http_response += echo;// http_response += "\n";http_response += "\n";// std::string http_response = "HTTP/1.0 200 OK\n";// http_response += "Content-Type: text/plain\n";// http_response += "\n";// http_response += "hello, i'm from the futurn\n";// 发送响应报文send(sock, http_response.c_str(), http_response.size(), 0);}}close(sock);return nullptr;
}int main(int argc, char *argv[])
{if (argc != 2){Usage(argv[0]);exit(-1);}int sock = Sock::Socket();Sock::Bind(sock, atoi(argv[1]));Sock::Listen(sock);while (true){pthread_t tid;int new_sock = Sock::Accept(sock);// int *psock = new int(new_sock);// pthread_create(&tid, nullptr, handler, psock);}return 0;
}
  • index网页构建:
<!DOCTYPE html><html><head><meta charset="utf-8"></head><body><h5>hello, i'm baichen!</h5><h5>hello, 我是表单!</h5><!-- action是数据提交到哪 method是提交数据时使用什么方法,可自行测试GET、POST方法传递信息的不同 --><form action="/a/handler_form" method="POST">姓名:<input type="text" name="name"><br/>密码:<input type="password" name="passwd"><br/><input type="submit" value="登录"></form></body>
</html>


📕后记


参考书籍:《图解HTTP》

本篇文章白晨讲解了HTTP的背景知识、协议结构、状态码、相关技术知识以及服务器的编写,也算是讲解的非常全面了。其中也有一些知识由于篇幅问题,白晨并没有展开说明,比如HTTP的首部字段等,需要大家在这篇文章的基础上自行进行相关学习。下一篇文章,白晨准备讲解HTTP协议的升级版——HTTPS协议,通过学习HTTPS的学习,相信你会对HTTP协议有更深的理解。

如果大家有什么想和白晨交流的,欢迎私信白晨🎊。


如果讲解有不对之处还请指正,我会尽快修改,多谢大家的包容。

如果大家喜欢这个系列,还请大家多多支持啦😋!

如果这篇文章有帮到你,还请给我一个大拇指 👍和小星星 ⭐️支持一下白晨吧!喜欢白晨【网络】系列的话,不如关注👀白晨,以便看到最新更新哟!!!

我是不太能熬夜的白晨,我们下篇文章见。

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

svn 代码迁入gitlab

window中安装好git客户端,右键空白处,点选git bash here进入git界面,输入命令 将svn38163之后的所有记录都备份那:git svn clone -r 38163:HEAD svn地址 --no-metadata trunk(本地电脑目录名) --username *** 备份所有提交记录:git svn clone svn地址 --no-metadata …

Linux安装Python 以及过程中的命令详细介绍

下载源码包 打开 Python 官网 找到需要的安装包 获取了资源的链接后&#xff0c;进入Linux下载&#xff0c;wget意思是webget&#xff0c; 即下载 wget https://www.python.org/ftp/python/3.10.7/Python-3.10.7.tgz目录下会新增 这样源码包就下载好了。 如果下载太慢&…

二叉树与递归问题

目录 一&#xff1a;求二叉树的深度 二&#xff1a;二叉树反转 三&#xff1a;二叉树镜像判断 四&#xff1a;递归的终止条件 用递归解决的问题必须注意的&#xff1a; 递归的终止条件&#xff0c;也就是递归的出口&#xff08;否则&#xff1a;栈溢出&#xff09;递归的过…

决策树简介

决策树简介 决策树实际上是一个布尔函数,它的输出可以是“0 或 1”或“-1 或 +1”或“-1、0 或 +1”。决策树的大小等于其中存在的节点数,其深度等于从顶部到根的最长路径的长度。 错误率:训练集始终是给模型的标记示例,模型训练得越多,其错误率就越低。 训练样本 = { set…

程序里对象很深很大,可以用这个设计模式缓解一下

如果一个类的有非常多的属性&#xff0c;层级还很深。这个妥妥的是我的对象很大&#xff0c;你创建的时候忍一下......那你每次要创建的时候都忍一下&#xff1f;有没有一种好的方式让我们创建太的时候使用体验更好一点呢? 今天的文章里就给大家介绍一种设计模式&#xff0c;来…

C++多线程的线程返回值问题

对于多线程可执行对象的返回值是何时返回&#xff0c;以及得到的呢&#xff1f; 对于需要用到线程返回值的线程要使用future类对象来实现 文章目录future对象async()launch::deferred参数launch::async参数packaged_taskpromisefuture对象 是一个类模板 提供访问异步对象的操作…

优化 | Management Science 7-8月文章精选: 信息系统中的运筹学

作者&#xff1a;Evelyn Yao 清华大学本科在读 在“Management Science近期论文精选”中&#xff0c;我们有主题、有针对性地选择了Management Science中一些有趣的文章&#xff0c;不仅对文章的内容进行了概括与点评&#xff0c;而且也对文章的结构进行了梳理&#xff0c;旨在…

非零基础自学Java (老师:韩顺平) 第13章 常用类 13.5 StringBuffer类

非零基础自学Java (老师&#xff1a;韩顺平) ✈【【零基础 快速学Java】韩顺平 零基础30天学会Java】 第13章 常用类 文章目录非零基础自学Java (老师&#xff1a;韩顺平)第13章 常用类13.5 StringBuffer类13.5.1 基本介绍13.5.2 String VS StringBuffer13.5.3 String 和 Str…

HashMap

1.HashMap集合 1.1HashMap集合概述和特点【理解】 HashMap底层是哈希表结构的依赖hashCode方法和equals方法保证键的唯一如果键要存储的是自定义对象&#xff0c;需要重写hashCode和equals方法 1.2 特点 HashMap是线程不安全的实现&#xff1b; HashMap可以使用null作为key…

【Pytorch深度学习实战】(9)神经语言模型(RNN-LM)

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

第一视角体验搭载全志T507-H的开发板MYD-YT507H开发板

如今车规级芯片市场潜力巨大&#xff0c;需求旺盛&#xff0c;芯片都在逐渐走向国产化。本文要介绍的主角是MYD-YT507H开发板&#xff0c;该开发板是米尔科技结合全志国产工业级平台CPU——全志T507-H芯片研制的CPU模组&#xff0c;全志T507-H可广泛用于电力物联网、汽车电子、…

目标检测开源框架YOLOv6全面升级,更快更准的2.0版本来啦

9月5日&#xff0c;美团视觉智能部发布了YOLOv6 2.0版本&#xff0c;本次更新对轻量级网络进行了全面升级&#xff0c;量化版模型 YOLOv6-S 达到了 869 FPS&#xff0c;同时&#xff0c;还推出了综合性能优异的中大型网络&#xff08;YOLOv6-M/L&#xff09;&#xff0c;丰富了…

一个div靠左另一个靠右

1.使用flex布局<style>#back{border: red solid 1px;width: 800px;height: 500px;display: flex;align-items: center;}#left{border: blue 1px solid;width: 100px;height: 100px;justify-content: flex-start;}#right{border: blue 1px solid;width: 100px;height: 100…

【前端进阶】-TypeScript类型声明文件详解及使用说明

前言 博主主页&#x1f449;&#x1f3fb;蜡笔雏田学代码 专栏链接&#x1f449;&#x1f3fb;【TypeScript专栏】 前三篇文章讲解了TypeScript的一些高级类型 详细内容请阅读如下&#xff1a;&#x1f53d; 【前端进阶】-TypeScript高级类型 | 泛型约束、泛型接口、泛型工具类…

Google Pub/Sub入门

什么是Google Pub/Sub&#xff1f; 首先他是一个messaging buffer/coupler消息缓冲区/耦合器&#xff0c;Decouples senders and receivers解耦发送者和接收者。 一些特性&#xff1a; 使用 Dataflow 注入分析事件并将其流式插入到 BigQuery免运维、安全、可伸缩的消息传递系…

MySQL基础总结合集

MySQL是啥&#xff1f;数据库又是啥&#xff1f; MySQL&#xff1a; MySQL 是最流行的关系型数据库管理系统&#xff0c;在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System&#xff1a;关系数据库管理系统)应用软件之一。 数据库&#xff1a; 数…

基于nodejs+vue的读书会网站

实行网上读书会网站&#xff0c;对其改善目前人们读书现状提供一些帮助和优化措施&#xff0c;为人们在未来看书节约了很多时间&#xff0c;使得人们在未来利用自己有限的时间可以看到更多对自己有益的书籍。 基于Vue的读书会网站的实现&#xff0c;通过网上系统的研发构造&…

你是否想过,GitHub Pages也可以自动构建?|原创

本文讲述了如何利用 GitHub Actions 来自动构建 GitHub Pages 项目&#xff0c;免去繁琐的手动构建再提交过程&#xff0c;让你专注于写作。点击上方“后端开发技术”&#xff0c;选择“设为星标” &#xff0c;优质资源及时送达GitHub Actions 自动构建之前的文章我们已经讲过…

Tomcat 在IDEA中运行Tomcat,控制台乱码问题的解决方案

IDEA中运行Tomcat,控制台乱码问题的解决方案试了好多种网上的方案(只有这一种能解决)环境:jdk 11 idea 2022.2.4 tomcat 9.0.54解决方案: 1.打开tomcat的配置文件(apache-tomcat-9.0.54\conf\logging.properties)将文件中的java.util.logging.ConsoleHandler.encoding =…

el-tree增加提示语

element ui tree树形控件加提示信息<el-tree :data="tieLinedata" :props="defaultProps" @node-click="handleNodeClick"><span class="span-ellipsis" slot-scope="{ node, data }"><span :title="no…