一、应用层协议HTTP
1. 认识http协议

这个是博主用自己的服务端,在浏览器上访问得到的http请求。



可以看到,http的应答就是一个长字符串,只不过这个字符串通过\r\n被分成了多行。

http请求第一行称为请求行,每行的最后都有一个标准的换行符,接下来就是请求报头部分了,每一个都是Key->Value的字符串,按照这种格式。接着就是标准的换行符,紧跟着就是请求正文部分了。
那么,大家就要思考一个问题了。
什么是协议,为什么要有空行呢?
协议前面我们说过,协议的本质就是一种约定,其实就是一个结构体。
那为什么要有空行呢?
是为了区分报头和有效载荷的。
正文部分可以有也可以没有。

http应答第一行被称为状态行,紧接着是响应报头也是Key->Value格式的字符串,后面跟着标准换行符,接着便是空行,最后是正文部分。
同理这里的空行就是为了区分报头和响应正文的。
那如何理解正文呢?
正文是可有可无的。举一个例子来理解它。
人类上网的过程其实就分为两种:1、得到信息 2、上传信息。上网的过程其实就是客户端,服务端两个进程之间在通信,进行IO。比如:你在刷抖音就是为了获取短视频,浏览网页就是为了获取信息。
当我们使用网址访问网页时,http请求就是没有正文的,目的是为了获取资源,而http应答时是包含正文的,因为它要给我们返回搜索结果。
2. 理解http协议
现在我们对于http的物理结构有了基础的了解,那么我们看看http协议的链接吧。

这个整体我们叫做URL,即统一资源定位符。https这部分是使用哪一个协议,chat.deepseek.com是域名,其实就是公网IP,将来这个域名会经过解析变成公网IP,这个解析的过程叫做DNS。
那么,我们在使用这个网址时是为了获取信息的 ,当然了也可以是其它网址,比如我们要获取短视频,图片商品信息...等。那么在没有得到这些资源之前,资源在哪里?这些资源在服务器上,即云服务器上。那要如何找到云服务器呢 ?所以要获取云服务器的公网IP地址。
那找到云服务器之后呢?我们只是找到了这台机器,并没有获取到想要的资源呢?
那就要提出一个新的问题了,这些资源在云服务器上是以什么形式存在的呢 ?Linux下一切皆文件,这些资源是以文件的形式在云服务器上存在的。
那Linux下又不是只有一个文件,这么多的文件该如何找到呢 ?所以文件就必须要有路径。
所以,这段协议的后半部分是用来表示指定路径下的文件。
而主机是具有唯一性的,路径也是具有唯一性的,所以这段协议就能够标识互联网中唯一的一个文件。
注 :域名后面紧跟的/这个是根目录吗?不一定是根目录,它是web根目录,即任意一个目录。
URI是一种特殊的URL。
Client发送过来的请求,要如何把请求的数据发送给Client呢?
就是我们所写的软件server,所以说网络通信本质上是两个进程之间在通信。
可是对端怎么知道应该使用哪一个进程进行通信呢 ?所以要有端口号,不要忘了端口号就是用来标识进程的唯一性的。
所以访问网址时要带上端口号,那为什么刚才的网址没有带上端口号呢?
因为https,http...这些协议是知名协议,它们的端口号是固定的。访问的时候这里的端口号是省略了的,但并不是没有,浏览器会自己加上。

这里我们还需要关注一个东西:?及之后的部分我们叫做 url带参,这部分就是我们要上传信息可以用到的部分。
举一个例子就懂了。

圈起来的这部分就是带参部分。
需要注意的是helloworld是常规字符,所以这里没有变化。如果我们用一些特殊字符这里就会出现变化。

这里就出现了变化,进行了编码,这是因为url中不允许出现特殊字符,会出现乱码。那么要如何做呢?
将需要转码的字符转为16进制,从右往左,取4位(不足四位直接处理,指比特位),每2位做1位(指16进制,两个16进制就是8个比特位,即一个字节),前面加上%,编码成%XY格式。
通过观察可以看到,http协议里请求与应答都包含http版本,那么为什么协议里要包含版本呢?
首先http版本分为http/1.0、http/1.1、http/2.0,那为什么协议里要带版本呢?
举一个生活中的例子,我们所用的app都经过更新吧,之所以更新是因为应用有了新的特性,比如新增了刷视频的功能,点赞功能等等,这时候就会有人选择更新,有人不更新,所以市面上就会有新老客户端,而有些特性是需要客户端和服务端的http版本是一样的才可以,所以协议里要带有http版本。

以这张图进一步来理解http协议。
POST就是表明要对资源执行什么操作,后面跟着的是资源的路径,协议版本在请求行中单独指定。
HOST的内容就是域名,即公网IP地址。
User-Agent就是指明当前浏览器的信息,OS的平台,以及体系结构。
举个例子:你为什么在浏览器搜索app时,它会给你匹配到适合当前系统的app呢,比如windows系统就会搜索到适合windows版本的app,就是因为User-Agent记录着相关信息。
Content-Length就是有效载荷的长度,表明有没有正文,正文的长度是多少 ,我们把这种标识正文长度的描述叫做自描述字段。
3. 关于uri的说明
uri:/表明请求目标服务器的首页。
那什么是首页呢?
如果uri是'/',表明请求的是首页,就是在根目录下的index.html文件(不一定是这个文件,也可以是根目录下的其它文件,但仅限于这个首页是物理文件)。
uri:/a/b/c.html(这里假设是这样,只要不是 / ),表明请求目标服务器web根目录下的指定路径下的文件。
那什么是web根目录呢?
就是指定系统下的任意一个路径,以目录组织的形式,把资源文件保存起来。
我们在点击图片,视频时,向服务端发送http请求,服务端给我们发送http应答时,怎么知道资源是什么类型的呢?
所以就需要有Content-Type属性。
Content-Type就是用来表示正文类型的。
Referer:当前页面是从哪个页面跳转过来的。
Connection:keep-alive选项表示长连接,期望可以进行长连接。
TCP协议是面向字节流的,存在数据粘报的问题,所以要怎么解决这个问题呢 ?就需要根据Content-Length来确定正文的长度,如果没有全部读取就要继续读取,这就是长连接。
Accept-Encoding表示压缩,解压,告诉服务器客户端支持哪些压缩算法。
Accept-Language表示接收语言的类型。
4. HTTP的状态码


这里我们挑几个说说。
201和204就类似我们在CSDN上发布文章和删除文章。
400,401,403这三个状态码就分别像用户登录时需要填写密码,密码只支持数字和字符,你就非填写一些规定之外的字符就会出现400,而401就是用户登录输入密码,密码输错了返回的就是401。
403就是没有权限去访问这个页面了,服务器把你的权限给关闭了。
404代表访问的链接不存在,客户端发起了不存在的链接请求就会返回这个状态码。
最后以5开头的状态码就是属于服务器的状态码了。
以3开头的状态码分为 永久重定向和临时重定向。
那我们就要理解什么才是永久重定向和临时重定向了,举一个例子来帮助理解。
比如说学校的东门有一家麻辣烫,你和你的舍友今天中午要去吃麻辣烫,所以你们就去学校东门这家麻辣烫了,但是因为学校东门最近在修路,导致东门那边的环境不太好,所以麻辣烫老板决定将店门暂时开到学校西门,但是又没有办法让全部的顾客都知道这件事,于是老板在东门的店面上贴了一张纸,告诉顾客由于东门环境不太好,因此暂时迁至西门,请各位顾客来西门品餐。你和你的舍友看到了这个消息,就去西门吃麻辣烫去了,这就叫做临时重定向。
重定向是因为提供服务的一方,服务的地址(新的url)发生了变更,要求客户端更改访问地址,去新地址访问。
等过了一段时间以后,你和你的舍友又要去吃麻辣烫,但是这时候你们犹豫了到底要去西门还是东门呢?最近东门的路应该已经修好了,老板上次说临时迁至西门,我们去东门吧。于是你们去了东门,到了之后发现,东门的店面上写着店面永久迁至西门,所以你们又去了西门,以后再也不会去东门了,这就叫做永久重定向。
所以,永久重定向和临时重定向的区别在于影不影响客户对地址的认识。
Location搭配3xx状态码使用,告诉客户端接下来要去哪里访问(用于重定向)。
5. HTTP的方法

这里我们主要说GET和POST方法,其它方法一般用不上。
我们上网无非就两种行为:1、获取资源 2、上传资源。
. GET方法
获取资源就类似于我们在网页端搜索框里搜索时的场景,需要使用到GET方法。在我们自己的服务端里也使用到了GET方法来请求资源。这里给大家贴一张图片。

这里我们默认请求到了web根目录下的index.html文件(即首页)。
那上传资源又是怎么回事呢 ?这个一般是html的表单给我们提供了上传能力。给大家贴一张图片来看看。

method就表明了使用POST方法,input就会被解释为输入框。
GET传参,通过url进行参数传递,既可以获取信息又可以上传信息。
例如:用户登录页面时需要输入用户名和密码,前端通过from表单拿到参数,将参数传递给http请求,这样服务器就可以根据请求来解析用户的需求了,进而处理请求。这就是通过url参数进行传递的(但使用GET方法这样进行传参是不安全的)。
获取信息就类似于用户搜索,想得到一些信息,服务器就会在云服务器上按照指定的路径进行查找资源,进而给用户http应答。
那要如何区分上传信息和获取信息呢?
很简单,只需要看链接是否有?和参数就可以了,有?的代表要上传信息,否则就是要获取信息。这个结论只针对于GET方法成立。

. POST方法
POST方法通过正文来传参的。比如用户登录时填写的用户名和密码不再像GET方法一样,通过url传参,将参数写在http协议的请求行里,而是写在http协议的正文部分。
总结 :GET方法用来获取静态资源(web根目录下的文件),GET方法传参,通过from表单传参,参数跟在url后面。POST传参,参数写在http协议的正文部分。
GET、POST方法都是明文传参,都不安全,但相对于GET方法来说,POST方法相对安全 (因为参数写在了正文里,通过链接是看不到信息的),POST可以用来传递参数较多的情况,GET方法传参,回显url中,不私密。
登录,支付,注册等场景都是需要使用POST方法的。
当我们登录输入密码时,密码这个信息就会被包装在http协议里,发送给服务器,那么在这个局域网中,其它主机也是会收到你的密码这个http协议的,只不过被其它主机给丢弃掉了,如果其它主机不丢弃呢?那岂不是泄露隐私了。所以http协议是不安全的。
在http协议和tcp协议之间,有一个TLS/SSL,它会对http协议进行加密,发送给对端,再进行解密,这样就保证了安全性。这个新的协议就叫做https协议。
http协议是一个无连接的,无状态的协议,即每次请求都需要建立新的连接,且服务器不会保存客户端的状态信息。
http协议虽然是基于tcp协议的,tcp协议是面向连接的,但是这跟http协议是无关的,回想http协议的格式,是没有连接的。
那什么叫做无状态呢?
对用户的历史请求和用户行为,不做任何记录就是无状态的。
比如:大家都看过vip视频吧,看vip视频我们需要给指定的账户进行充值并且需要登录才可以。假如现在我们第一个vip视频看完了,要看第二个,第三个,第四个vip视频呢?就意味着我们要跳转播放页面,假设http是无状态的,那么就需要用户每次都需要进行登录账号,那岂不是烦死用户了。所以HTTP为了保证能够对用户进行一定程度的状态保持功能,就要求服务器,浏览器,HTTP提供 Cookie和Session来达到这个目的。
Cookie:用于在客户端存储少量信息,通常用于实现在线管理与会话保持功能。
当用户登录时输入用户名和密码,就会被http协议包装发送给服务器,服务器经过认证,通过之后给客户端进行http应答 就会带上Set-Cookie,里面保存的就是你的账户信息,因此,Cookie也是属于应答报头的属性之一,浏览器就会记录下Set-Cookie的信息,至此以后,客户端再也不用输入自己的用户名和密码了(在一定的有效期内)。这不就是实现了免密码登录吗!
Cookie技术 :1、应答的报头属性之一,客户端要自动的保存起来cookie信息,保存信息有两种方法,一、是文件级,二、是内存级。
2.从此往后,浏览器在向目标服务器发送第n次http请求,请求报头会自动携带当前保存的cookie信息。
但是这种方法是不安全的,为什么呢?
举个例子,大家都听过黑客吧。假如黑客现在向你的电脑植入了一个木马病毒,拿到了你的cookie信息,那岂不是拿到了你的用户名和密码,如果他和你访问的是同一个网站,那不就可以利用你的账号干坏事了。这就叫做盗号,拿你的号就可以欺骗你的亲朋好友了。因此这种做法是不安全的。
所以有了session,每个用户在登录的时候都会在服务器形成一个session文件,每个session文件都有自己的session_id ,该文件里保存的就是用户的账号信息,以及浏览信息等各种信息,用户在向服务器发送http请求的时候,经过认证通过,服务器依然会给客户端发送http应答,该应答中依然包含cookie信息,只不过这次cookie信息中包含的内容不再是用户的信息,而是session_id,用户的信息被保存在了服务器中。
这样即使被盗号,他拿到的也是session_id,依然能够通过session_id访问你要访问的服务器,但是他拿不到你的隐私信息了,避免了隐私信息的泄露,但依然无法避免被盗号。但盗号这种情况可以得到缓解,根据地域的位置可以初步判断账号是否安全,比如你不可能一瞬间就从北京跑到云南去。登录的时候查找session_id是否存在就可以了。
但是服务器有这么多的session文件,有些文件过期了,有些文件需要释放,有些文件需要保存,那么这些文件需不需要管理呢 ?答案是需要的,先描述在组织。