Linux网络:应用层http
文章目录
- 1. http简介
- 1.1 http是什么
- 1.2 为什么需要http
- 2. url
- 2.1 url结构组成
- 2.1 url的编码与解码
- 3. http请求与应答
- 3.1 http请求
- 3.1.1 请求行
- 3.1.2 请求报头
- 3.1.3 请求正文body
- 3.2 http应答
- 3.2.1 状态行
- 3.2.2 报头
- 3.2.3 正文
- 4. http相关周边知识
- 4.1 https
- 4.2 http的无连接和无状态
- 4.2.1 cookie
- 4.2.2 session
- 4.2.3 http访问服务器资源的简单过程
1. http简介
1.1 http是什么
http协议全称是Hyper Text Transfer Protocal,即超文本传输协议。
超文本本质就是超越了传统文本线性阅读方式的文本,超文本内部包含各种超链接,可以通过这些链接实现跳转,进而达到非线性阅读——几乎所有的网页都是超文本。
传统的http协议中,传输层都是基于TCP通信,直到http3版本中,开始正式采用UDP传输层协议。
1.2 为什么需要http
OSI七层模型或者TCP/IP五层模型,本质应对的是实际网络通信中不同层的问题。
应用层是模型中的最上层,需要处理网络通信中,通信双方实际与通信诉求相关的数据——例如客户端向服务端请求什么资源,服务端根据客户端实际请求返回相应资源数据。
而在实际通信过程中,请求一方如何请求,应答一方如何应答,如果没有相应协议规定,通信几乎是无法进行的,因此应用层的http通信协议因此诞生。
在TCP/IP协议栈中,应用层是唯一的需要程序员手动实现的,但已有http协议的存在,应用层的具体编写依照http协议即可。
2. url
url中文名是统一资源定位符,是用于资源访问时进行资源定位。
资源本质就是服务器上的文件,我们借助浏览器,通过url
访问这些资源,所以我们平时所熟知的网址,就是url
。
http
本质作为url
的一部分存在,具体表示访问服务器资源时,在应用层采用什么协议。
2.1 url结构组成
我们来看一个简单的url
。
http://www.baidu.com:80.
这段url
中,可以分为三个部分:http协议,域名和端口。
www.baidu.com
:域名。网络通信的实质,本质是不同主机上的两个进程在通信,所以通信的前提——定位主机和定位特定主机上的进程。定位主机本质可以通过IP实现,而一台机器上一个端口必定只对应一个正在活跃的进程。
域名本质就是IP,通过DNS
,即域名系统进行域名解析,最终得到相应的主机IP,进而实现访问。
80
:表示端口。用于定位特定主机上的进程。80
端口可以省略不写,因为现今浏览器功能强大,可以自动补全——http协议默认访问的就是80号端口。
2.1 url的编码与解码
url
为什么需要urlencode
和urldecode
呢?本来实际的编码方式,如UTF-8
就已经支持中英文。
主要原因是,url
在识别时,某些字符具有特殊功能,比如?
后面的内容表示要上传给服务器的内容。
但是,如果实际url
中存在上述字符,但实际上仅仅作为字符本身,而不是用于特殊功能,为了防止误解析,就要对这些不安全字符进行编码。当然,如果是安全字符,即不具备特殊功能的字符(也不尽是如此,比如中文往往需要编码),就无需编码。
具体的编码方式:
如果是ASCII字符,那么一个字符一个字节,这一个字节使用两个16进制进行表示,并在最前面添上%。
如果是中文,那么根据不同的编码方式,通常为UTF-8
,占3个字节,使用6个16进制表示,同时最前面添上%。
解码方式与编码方式相照应。通常,使用浏览器访问服务器资源时,浏览器做好urlencode
,服务器端做好urldecode
.
3. http请求与应答
3.1 http请求
在浏览器中借助url
来对服务器资源进行访问,但最终浏览器通过网络发送给服务器的信息并不就是url
,而是会将相关信息整合为一个http请求
,这个请求具备相应的格式。
需要注意的一点是,发送的这个http请求,上图展现出现,似乎是一个复杂结构,但在网络传输中,本质都是字节流传输——上述http request本质就是进行了序列化的字符串,这个序列化并未依赖任何第三方库,而是直接应用层依据http协议自身实现的——这个序列化整体比较简单,只不过其中的换行符明确规定为\r\n
,不能是\n
。
3.1.1 请求行
请求方法:
- GET:较为常用的用以获取服务器资源的方法。
- POST:用于向服务器上传数据,通常用于上传表单数据。
- PUT:用于上传文件到服务器指定
url
位置。 - DELETE:与PUT相反,用于从服务器指定
url
位置删除文件 - HEAD:与GET作用类似,只不过只返回GET中获得的http response中的报头部分,并不获取正文
- OPTIONS:用于获取服务器指定URL资源支持哪些请求方法。
需要说明的是,上述方法中GET和POST的使用是最多的,其它方法使用很少,甚至现今http协议版本不再支持。
uri:
uri
是统一资源标识符,它的内容即上述url
中所包含的具体路径。
https://news.qq.com/rain/a/20250917A04G5N00
这是腾讯网上某条新闻的访问url,其中uri
截取的部分就是/rain/a/20250917A04G5N00
。
网络通信本质是进程间通信,服务器上的进程要获取相应资源,并将其通过网络返回给浏览器。最主要的资源形式是什么?服务器上的文件。服务器如何定位文件——通过文件的路径。
上述uri
本质就是服务器上特定资源的路径。
需要说明的是,uri中最前面的/
,并不直接代表实际根目录,而是指web根目录,实际可代表服务器上的任意目录。具体来说,就是服务器端本身就会对uri做进一步处理,将路径中的/
替换为相应的目录路径,即实际web根目录会被服务器端特定替换为相应目录。
http版本:
http
有多个版本,http0.9
,http1.0
,http1.1
,http2
等等,其中最广为流传的版本就是http1.1
。
为什么http请求中要包含特定的http
版本?
不同的http版本,往往会有不同的规定,发送http请求时,添加相应的http版本,就是希望服务器端也通过相同的http版本规定,实现两端网络通信。
3.1.2 请求报头
http请求报头均为kv结构,通常是客户端发送给服务器的附加信息。
报头中内容写什么,写的时候要注意怎样的格式,这些都是http协议中规范好的行为。
以下介绍一些常用的报头内容:
- Host:通常要包含,表示域名。
- User-Agent:表示客户端类型。比如说是手机上的app,还是电脑端上的浏览器应用,而根据客户端类型,服务端可以返回相应适配界面。
- Accept-Language:表示客户端偏好语言。
- Content-Type:表示客户端请求体body中的正文数据格式,以便服务端进行解析。
- Content-Length:如果客户端请求体中包含body正文数据(通常是在POST方法中含,GET方法一般没有),这个属性表示正文数据长度,单位是字节。在UDP通信中,由于UDP本身传输数据报,内核层面自动保证接收数据完整性,不存在粘包问题;但是TCP通信,本身是流式传播,需要在应用层自主维护接收数据的完整性,解决粘包问题,这个字段正是为此诞生的。
- Referer:表示当前请求从哪个界面跳转过来——即记录访问的上一个资源的url
- Connection:连接行为。通常两个选项:keep-alive(http1.1中的默认行为)和close。前者完成通信后,不立刻关闭,表示长连接;而后者完成一次通信后,立刻关闭,为短连接。
通过上述属性字段,可以看出http请求的报头属性中,有相当一部分内容用于规范服务端的http应答
3.1.3 请求正文body
http
请求结构,由于包含三部分信息,需要对三部分信息做区分。
从开始读取到第一个换行符的内容为请求行,行内使用空格区分不同内容;请求行以下,一直读到单一换行符之前,表示报头内容,报头内的每一行用冒号和空格区分属性和值;单一换行符之后内容为body部分,所应读取body长度由报头中的Content-Length规定。
综合来看,整个http request的结构设计是较为周密的,能够通过该结构提取相应不同信息,并且能够在TCP通信中,解决粘包问题,设计逻辑是自洽的。
3.2 http应答
对于服务端,在接收到客户端http
请求后,进行相应解析和处理后,会向客户端通过网络返回http
应答。
http
应答的格式如下:
3.2.1 状态行
HTTP版本:
标明所使用的http协议版本,方便客户端收到应答后,能够进行符合协议版本的解析。
状态码
:
状态码本质就是一个整数,表示服务端对于相应http请求的一个处理结果。
状态码描述就是一个字符串,用以描述相应状态码所表示的信息。
- 1XX: 这种状态码用以服务端告知客户端,客户端的请求我已正常收到并处理,客户端请继续进行
http请求
。比如说100,代表continue
,在客户端上传大文件时,可能需要多次分批上传,100就表示之前你上传的我已全部收到,请继续上传。 - 2XX: 表示正常相应
http
请求。针对不同的http
请求:GET通常返回200,表示OK;POST通常返回201,表示资源已正常上传;PUT,DELETE通常返回204,即请求成功,但response中body为空。 - 3XX: 重定向状态码。最常见的301,永久重定向;302临时重定向;304表示内容未修改。
- 4XX: 客户端相关。400表示请求错误,401未授权,403禁止访问,404未找到相应资源
- 5XX: 服务器相关。最常见的502,表示网关错误。
状态码描述:
- 100:continue。
- 200:OK。通常表示GET请求响应成功。
- 201:Created。表示POST创建资源成功。
- 204:No Content.表示http response中的正文为空,通常用于PUT或DELETE成功
- 301:Moved Permanently。永久重定向,访问旧域名会自动跳转到新域名。永久重定向用于访问资源被永久移动到其它位置,推荐使用新url进行访问(旧url可能不再保留),浏览器也会进行缓存——搜索时,优先展示的新url内容。
- 302:Found。临时重定向,在服务器进行维护时会经常出现,表示资源被暂时移动到其它位置。临时重定向的临时,短暂——相关资源被临时重定向时,仍推荐使用原url进行直接访问,并且浏览器通常不会缓存临时重定向的url。用户登陆界面的跳转通常也是临时重定向——临时性,登陆后便会重新跳转到主页。
- 304:Not Modified。表示内容未修改。客户端访问资源时,可能会对资源进行缓存,实现在本地直接访问。这个状态码即表示要访问的资源没有别修改,可直接访问本地缓存,因此http response中的body也就为空——减少网络传输的数据,提高效率
- 400:Bad Request。说明http请求本身的内容有问题。
- 401:Unauthorized。通常表示用户访问相关资源需先进行身份验证,即登陆等。
- 403:Forbiddened。表示用户不具备相应的访问权限。
- 404:Not Found。表示客户端请求的资源不存在。
- 502: Bad Gateway。通常被代理服务器返回,表示代理服务器无法访问上游服务器以获取返回资源。
3.2.2 报头
http请求和http应答中的报头内容大部分都是相同的,此处不再赘述。
3.2.3 正文
由于http请求通常都是要求获取资源的,因此http应答中的body部分通常都是非空。
关于http应答中状态行,请求报头和正文,整体结构与http请求相同,具体区分和粘包问题的解决亦与http请求相同。
4. http相关周边知识
4.1 https
通常意义上,GET方法用以获取资源,POST方法用以上传资源,但是GET方法也可以传递商量数据,一般通过url中?特殊字符进行传递,?后的内容表示要上传的数据。
所以,如果上传数据,GET中的内容最终会显示在http
请求状态行中的uri
中,而POST则是存储在正文body中。
但是,上面两种方法都是明文传参,非常不安全,如果相关的http
请求或应答,被劫持了,直接造成信息泄漏。
正因为http协议的不安全,https被引入了。https本身是基于http的,只不过额外添加了加密模块SSL或者TLS,这些加密模块已经由成熟的第三方库实现,实际加密时,应用层调用相关库即可(如果从OSI七层模型来解析,TLS或SSL实际工作在会话层)。
需要说明的是,https的加密是对整个http请求或应答加密,而非单一正文加密。
4.2 http的无连接和无状态
http本身具有无连接和无状态的性质。
http本身是基于TCP的,TCP需要建立连接和通信双方保持连接状态相关信息,但是TCP本质属于传输层,http应用层并不关心传输层的连接建立,因此http是无连接的。
http是无状态的。http协议本身并不进行状态维持,即http的访问和应答是无记忆的,本身不会对历史请求和相关行为做任何记录。
举个例子,访问一个网站,要求登陆,登陆后,关闭这个网站;当再次访问这个网站时,由于http是无记忆的,因此会要求再次登陆,接下来所有的关闭后再访问,都要求再次重新登陆。
http无记忆带来的上述行为显然会使得用户体验极差,并且每次都需要用户重新登陆,通信效率也降低了。
而我们在访问网页时,一旦登陆后,一段时间内再次访问该网页,默认是自动登陆的,这显然不符合http
无记忆的性质,为什么?
4.2.1 cookie
http为了支持记忆性,在报头中引入了cookie属性。cookie的值就是曾经访问该网站的历史信息,以登陆为例,就是相应的用户名和密码。
实际上,记忆性支持更需要的是客户端和服务端的额外维护。客户端要在本地缓存曾经的历史信息,然后再访问相应资源时,通过http请求中的cookie将历史信息带上,而服务端也要支持对http请求中的历史信息做处理,根据处理结果,再返回相应资源。
客户端实际缓存的cookie信息,可能是内存级的,也可能是磁盘级的。内存级cookie信息,当前客户端会话结束,客户端退出后,下次再访问就不存在了;磁盘级cookie,每次客户端启动均有效,但是也存在保存时间限制,时限超过也会被从磁盘上删除。
4.2.2 session
cookie
这种保存历史信息的方式,本质还是直接存储在http
请求中,虽然存在https
的加密,但是仍然存在被劫持并且破解的可能。
为了进一步提高安全性,http协议又再次引入session属性。
信息直接保存在传输数据中,不安全;信息保存在客户端上通常也不安全,因为客户端通常都是个人电脑使用,缺乏有效的安全防护机制;但把信息保存在服务器上是相对更安全的,因为公司的服务器基本都有专门的安保团队进行安全防护,信息被泄漏的可能性较低。
session的实际使用中,第一次访问后,服务器端会维护一个session,其中存储了历史信息,然后给客户端返回一个唯一的session id。再次访问时,客户端在http请求报头中添加这个特定session id,服务器端收到请求后,拿这个session id进行比对,成功匹配便提取出其中所存储的历史信息。
4.2.3 http访问服务器资源的简单过程
我们以浏览器访问指定网页资源为例。
在浏览器中访问指定的url
,进行域名解析后,就向指定服务器发送http request
,其中可能包含相应的cookie
或session
信息。http request
本质就是一个字符串,是序列化之后的结果,用于网络通信中的流式传播。
服务器接收到http request
之后,首先对http request
进行反序列化,将其中的各种信息存储到特定结构的特定变量中,然后再对提取到的信息做处理,比如uri
中的webroot
的替换,判断相应资源是否存在,或者去核对匹配cookie
或session
。
服务器对http request
的整个处理过程,本质就是构建http response
的过程,只不过首先构建的是一个http response
的结构,其中存储有最终应答信息,比如我们实际访问的网页资源,就是一个html
文件,属于http response
的正文部分。最终,服务器发送http response时,首先对特定结构化数据进行序列化,然后再进行网络发送。
浏览器在接收到http response
后,首先反序列化,然后对内容做解析,我们最终看见的网页,都是浏览器引擎解析http应答正文数据(.html .js .css)后呈现的结果。在浏览器具体解析时,会依据报头中的相关内容,比如content-type等。