美文网首页计算机网络
网络(三):应用层HTTP

网络(三):应用层HTTP

作者: 意一ineyee | 来源:发表于2021-10-25 21:37 被阅读0次

    目录

    一、字符编码和各个码表
    二、HTTP
     1、HTTP的数据格式
      1.1 HTTP请求的数据格式 = 请求行 + 请求头 + 请求体
      1.2 HTTP响应的数据格式 = 响应行 + 响应头 + 响应体
     2、请求行和响应行
      2.1 HTTP请求的方法
      2.2 HTTP请求的URI
      2.3 HTTP的版本
      2.4 HTTP响应的状态码
     3、请求头和响应头
      3.1 常见的请求头字段
      3.2 常见的响应头字段
     4、请求体和响应体
      4.1 请求体编码/响应体编码
      4.2 请求体格式/响应体格式
    三、HTTP的安全问题

    网络(一):基础知识
    网络(二):传输层TCP、UDP
    网络(三):应用层HTTP
    网络(四):应用层HTTPS

    一、字符编码和各个码表


    首先了解一下字符编码和各个码表,因为HTTP里有URL编码和请求体编码/响应体编码这两个东西要用到编码的知识。

    • ASCII编码和ASCII码表

    计算机起源于美国,它们只能存储二进制的0和1,也就是说只能存储数字,那它们是怎么存储英文的呢?

    美国国家标准局推出了ASCII编码——用一个特定的数字来代表一个特定的字母,并且强制规定这个数字占一个字节。这样字母和数字一一对应的关系就形成了一张表——ASCII码表,考虑到实际使用,这张表里又塞进了阿拉伯数字和英文的标点符号,此外还塞进了一些特殊的控制字符,总之英文模式下键盘上能敲出来的东西都直接对应在这张表里了,总共也就128个。

    计算机在存储英文时,会采用ASCII编码把一个一个的字符编码成对应的数字存储起来。而计算机在显示英文时,又会把一个字节一个字节的数字解码成字符显示出来,因为在ASCII编码和ASCII码表系统下,一个字符占一个字节。

    • GB2312编码和GB2312码表

    后来世界各地都开始使用计算机,很多国家使用的不是英文,ASCII编码和ASCII码表根本不能满足他们的需求,比如我们中国就有6000多个常用的汉字,那计算机是怎么存储中文的呢?

    国家标准局推出了GB2312编码——也是用一个特定的数字来代表一个特定的汉字,只不过强制规定这个数字占两个字节。这样汉字和数字一一对应的关系就形成了一张表——GB2312码表,对于ASCII码表里的字符,保持其原编码不变,只是将长度由原来的一个字节扩展为两个字节,GB2312码表可以说是ASCII码表的中文扩展集。

    计算机在存储中文时,会采用GB2312编码把一个一个的汉字编码成对应的数字存储起来。而计算机在显示中文时,又会把两个字节两个字节的数字解码成汉字显示出来,因为在GB2312编码和GB2312码表系统下,一个字符占两个字节。

    • UTF-8编码和Unicode码表

    互联网发展之初很多国家都有一套自己的编码和码表,你不能识别我,我也不能识别你,你的电脑要想显示中文文件就得给电脑装一个“中文编码和码表系统”,你的电脑要还想显示俄语文件就还得给电脑装一个“俄语编码和码表系统”等等,一旦装错了字符系统,显示就会出现乱码,怎么解决这个问题呢?

    国际标准化组织ISO推出了Unicode码表——一个包含了世界上所有国家字符的码表,同样地在这个码表里任何一个字符都唯一对应着一个数字,它是一个很庞大的集合,现在的规模可达100多万。

    电脑上只要装一个Unicode字符系统,无论想显示那种语言的文件,只要约定好在存储文件的时候存储成特定编码方式的文件就好了,其它电脑就能正常解码并显示。

    但需要注意的是,Unicode码表只强制规定了哪个数字代表哪个字符,却没有强制规定这个数字占几个字节(上面ASCII码表和GB2312码表不仅强制规定了哪个数字代表哪个字符,而且还强制规定了这个数字占一个字节或者两个字节),这是因为Unicode码表过于庞大,很多排在后面的字符需要用三个字节的数字才能代表,那如果Unicode码表强制规定这个数字占三个字节,这势必会造成存储空间的极大浪费,比如一个英文字母本来只需要一个字节就能存储得下了,现在却要在前面两个字节里全部填0,文本文件也因此大出两三倍。于是就衍生出了针对Unicode码表的众多编码方式:UTF-8编码、UTF-16编码(两个字节或四个字节)、UTF-32编码(四个字节)等来规定这个数字占几个字节。其中UTF-8编码是目前使用最广泛的,它最大的特点就是可变长编码,会根据不同的情况用不同字节的数字来代表字符,比如当遇到英文字母时就还是一个字节、和ASCII码表一模一样,当遇到中文汉字时就是三个字节等等。因此在UTF-8编码和Unicode码表系统下,一个字符占几个字节是不固定的,一个字母占一个字节,一个汉字占三个字节,但“具体占几个字节”这个信息也会被编码存储在这个数字里,以便后续解码时能知道到底应该把几个字节的数据连续在一起解码。

    二、HTTP


    HTTP(Hyper Text Transfer Protocol),超文本传输协议,是互联网中应用最广泛的应用层协议之一。设计HTTP最初的目的就是用来传输HTML文本的、就是为了能让用户浏览网页(比如浏览器发送一个HTTP请求,服务器就返回一串HTML文本,然后浏览器把HTML文本解析、渲染成一个网页展示给用户),只不过后来HTTP能传输的数据类型非常广泛了(比如还能传输图片、音频、视频等),不仅仅是HTML文本。

    HTML(Hyper Text Markup Language),超文本标记语言,用来编写网页。所谓超文本是指HTML文本能表达超出文本之外的内容(比如<a href="test.html">点击跳转到测试页面</a>这个HTML文本,它除了能表达“点击跳转到测试页面”这个普通字符串文本之外,它还表达了这是个超链接、可以点击跳转到测试页面);所谓标记语言是指HTML文本是由一个一个的标签(比如<head><body>等)组成的。

    1、HTTP的数据格式

    我本地服务器上有一串HTML文本如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Login</title>
    </head>
    <body>
        <form action="/hw/login" method="post">
            <div>Username:<input name="username"></div>
            <div>Password:<input name="password"></div>
            <button type="submit">Login</button>
        </form>
    </body>
    </html>
    

    可以通过URLhttp://localhost:8080/hw/html/login.html请求到,浏览器加载出来的效果如下:

    现在我们就在浏览器里请求一下这个URL,并用Wireshark抓一下数据看看。

    选中HTTP请求或者HTTP响应,右键选择追踪流,再选择追踪HTTP流,就能看到这一次HTTP请求和HTTP响应的数据了。

    双击HTTP请求和HTTP响应,更是可以看到这一次HTTP请求和HTTP响应的二进制流(任何数据最终都是转换成二进制的0和1进行存储和传输的)。

    1.1 HTTP请求的数据格式 = 请求行 + 请求头 + 请求体
    • 请求行:是由HTTP请求的方法、HTTP请求的URI和HTTP的版本组成的;
    • 请求头:是由一堆请求头字段组成的;
    • 请求体:就是客户端传给服务器的一堆入参,GET请求没有请求体,POST请求有请求体。

    我们拿上面例子中HTTP请求的数据来套一下看看对不对:

    • 请求行:HTTP请求的方法为GET;然后是一个空格;然后是HTTP请求的URI;然后又是一个空格;然后是HTTP的版本为1.1;然后是一个回车换行;
    • 请求头:接下来就是一对一对的请求头key-value,请求头字段名、冒号、一个空格、请求头字段值、回车换行;(注意:所有的请求头字段结束后有一个回车换行)
    • 请求体:因为上面例子用的是GET请求,所以没有请求体,后面会举POST请求的例子,到时可留意一下请求体。

    补充:回车换行

    回车符(return):它的本意是回到当前行的开头。
    换行符(newline):它的本意是下移一行。

    Windows系统保留了最原始的做法,每行的结尾都会有一个回车符 + 一个换行符,文本编辑器只要见到这两个字符就会先回到当前行的开头、然后再下移一行显示,也就是我们口头上常说的换行。但是为了节省内存,Mac系统设计一个回车符的功能就相当于Windows系统一个回车符 + 一个换行符的功能,所以Mac系统每行的结尾只有一个回车符,文本编辑器只要见到回车符就换行;同理Unix系统每行的结尾只有一个换行符,文本编辑器只要见到换行符就换行。为了兼容各个系统,HTTP要求使用最原始的做法一个回车符 + 一个换行符来代表换行。

    1.2 HTTP响应的数据格式 = 响应行 + 响应头 + 响应体
    • 响应行:是由HTTP的版本和HTTP响应的状态码组成的;
    • 响应头:是由一堆响应头字段组成的;
    • 响应体:就是服务器发送给客户端的数据。

    同样我们拿上面例子中HTTP响应的数据来套一下看看对不对:

    • 响应行:HTTP的版本为1.1;然后是一个空格;然后是HTTP响应的状态码200;然后是一个回车换行。(短语是可选的)
    • 响应头:接下来就是一对一对的响应头key-value,响应头字段名、冒号、一个空格、响应头字段值、回车换行。(注意:所有的响应头字段结束后有一个回车换行)
    • 响应体:可见响应体就是我们本地服务器上那一串HTML文本。

    2、请求行和响应行

    2.1 HTTP请求的方法

    HTTP请求的方法一共有九个:

    • GET:GET请求一般用来查服务器的数据;GET请求没有请求体,传给服务器的一堆入参一般放在URL里,但是浏览器和服务器对URL的长度有限制,所以GET请求不能传输太多的数据,注意不是HTTP协议本身对URL的长度有限制。

    • POST:POST请求一般用来增、删、改服务器的数据;POST有请求体,传给服务器的一堆入参一般放在请求体里,无长度限制。

    • HEAD:发送一个HEAD请求就相当于发送了一个GET请求,只不过服务器返回来的数据只有响应行 + 响应头,没有响应体而已。(使用场景举例:在下载一个大文件之前,可以先发送一个HEAD请求,从响应头里获取到文件的大小,再决定是否下载,这样可以省流量。要是直接发送GET请求的话,服务器就是直接给我们传输数据、就是直接下载了)

    • PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH:不常用。

    2.2 HTTP请求的URI
    2.2.1 URI和URL

    URI(Uniform Resource Identifier),统一资源标识符,用于唯一标识一个资源。比如/hw/html/login.html可以唯一标识我本地服务器上的一个HTML资源,它就是一个URI,但是别人也可能使用/hw/html/login.html来唯一标识他们服务器上的一个HTML资源。

    URL(Uniform Resource Locator),统一资源定位符,用于唯一定位一个资源。比如http://localhost:8080/hw/html/login.html可以唯一定位我本地服务器上的一个HTML资源,它就是一个URL,我们可以通过URL直接找到某个资源。

    因为URL能唯一定位一个资源,所以它肯定也能唯一标识一个资源,因此所有的URL都是URI,但并非所有的URI都是URL,即URL是URI的子集。URI和URL的主要区别就是URL是全网唯一的,我们可以通过URL直接找到某个资源,而非URL的URI不是全网唯一的,它必须得配合协议、IP地址、端口号才能找到某个资源。

    2.2.2 URL编码

    国际标准化组织ISO强制规定URL里只能出现:

    • 英文字母A ~ Za ~ z
    • 阿拉伯数字0 ~ 9
    • 保留字符/?

    其它任何字符都必须经过编码后才能出现在URL里,比如中文,又比如/?之外的保留字符:#[]@!$&'()*+,;=

    我们客户端开发人员可以采用任意编码方式对URL编码,比如ASCII编码、GB2312编码等,但是如果决定采用这些编码方式,就必须先跟服务端开发人员约定好,以便他们能够正确对URL解码。

    但是实际开发中我们很少写对URL编码的代码,这是因为实际的URL(比如http://localhost:8080/hw/html/login)都被服务端开发人员规范成了合法字符;而GET请求传给服务器的一堆入参(比如username=123&password=4 5%6)是放在URL里,虽说有可能出现非法字符,但是它们也都被网络三方库内部默认采用UTF-8编码给编码掉了;而POST请求传给服务器的一堆入参是放在请求体里,谈不到URL编码了。

    那虽然我们客户端这边的网络三方库内部针对URL默认采用UTF-8编码,但服务端开发人员那边知道吗?他们接收到URL后万一用别的方式解码呢?实际开发中我们也很少跟服务端开发人员约定说“我们都采用UTF-8编码”啊,这是因为服务端那边的网络三方库内部也默认采用UTF-8编码来对URL解码。也就是说,现在客户端和服务端的网络三方库内部针对URL默认都采用UTF-8编码,大家都默认了......如果真得决定采用别的编码方式,那就去约定吧。

    采用UTF-8编码对URL编码的格式为:一个%,后面加上该字符在Unicode码表里对应的十六进制数字。比如我们用AFNetworking或者Dio发起一个GET请求http://localhost:8080/hw/login?username=123&password=4 5%6,其实这个GET请求真正上是http://localhost:8080/hw/login?username=123&password=4%205%256,空格" "会被编码成%20%会被编码成%25

    AFNetworking内部默认采用UTF-8编码对GET请求的参数编码(即对URL编码) Dio内部默认采用UTF-8编码对GET请求的参数编码(即对URL编码)
    2.3 HTTP的版本
    • 1991年发布了HTTP/0.9

    1、只支持GET请求
    2、只支持传输HTML文本

    • 1996年发布了HTTP/1.0

    1、新增支持POST请求等
    2、新增支持传输图片、音频、视频等
    3、浏览器每发送一个HTTP请求,都要与服务器建立TCP连接,数据传输完成后立即断开TCP连接

    比如我们在浏览器里访问一下http://baidu.com,浏览器就会与服务器建立TCP连接,服务器会返回一串HTML文本,浏览器收到后就会断开TCP连接。

    但是当浏览器解析HTML文本的时候,会发现HTML文本里引用了很多其它的资源:CSS、JS、图片等,此时浏览器就会针对每一个资源都发起一个HTTP请求去服务器获取,而每发起一个HTTP请求都意味着一次建立TCP连接和一次断开TCP连接。

    • 1997年发布了HTTP/1.1(最经典、使用最广泛的版本)

    采用长连接(Connection: keep-alive),多个HTTP请求共用同一个TCP连接

    比如我们在浏览器里访问一下http://baidu.com,浏览器就会与服务器建立TCP连接,服务器会返回一串HTML文本,但是浏览器收到后不会断开TCP连接。

    当浏览器解析HTML文本的时候,会发现HTML文本里引用了很多其它的资源:CSS、JS、图片等,此时浏览器就会针对每一个资源都发起一个HTTP请求去服务器获取,但是这些HTTP请求都共用的是刚才创建的那个TCP连接。那这个TCP连接什么时候断开?其实这个长连接有个超时时间,等传输完数据,然后再过超时时间这么长时间,这个TCP连接就会断开。

    • 2015年发布了HTTP/2

    HTTP/2主要是优化了数据传输的速度,对比HTTP/1.1和HTTP/2的速度

    • 2018年发布了HTTP/3

    HTTP/3进一步优化了数据传输的速度,传输层不再使用TCP协议,而是改用基于UDP协议的QUIC协议,QUIC协议会保证可靠传输。

    2.4 HTTP响应的状态码

    HTTP响应的状态码一共有五类:

    • 100 ~ 199:信息响应
    • 200 ~ 299:成功响应
    • 300 ~ 399:重定向响应
    • 400 ~ 499:客户端错误响应
    • 500 ~ 599:服务器错误响应

    常见HTTP响应的状态码:

    • 200 OK:请求成功
    • 400 Bad Request:服务器无法理解该请求(情况一:HTTP请求的数据格式真得有问题,那服务器就会自动给客户端返回400的响应,根本到不了服务端开发人员这一步。情况二:HTTP请求的数据格式没问题,到了服务端开发人员这一步,发现客户端少传参数了,比如要求客户端传name和age两个参数,结果客户端只传了name一个参数,那服务端开发人员就可能会给客户端返回400的响应)
    • 404 Not Found:服务器无法找到请求的资源(一般是HTTP请求的URL拼错了)
    • 405 Method Not Allowed:服务器禁止了使用当前方法的HTTP请求(一般是HTTP请求的方法用错了,比如服务器要求某个HTTP请求必须用POST,客户端却用了GET)
    • 500 Internal Server Error:服务器崩了(一般是服务端开发人员的代码写的有问题)

    3、请求头和响应头

    3.1 常见的请求头字段

    实际开发中我们很少写设置请求头的代码,这是因为很多事情都被网络三方库内部帮我们给做了,比如设置Host、User-Agent、Connection、Content-Type、Content-Length等,我们只需要调用API发起网络请求就可以了。当然有些情况下我们也可能需求去写设置请求头的代码,比如设置Accept、Accept-Charset,或者断点续传设置Range,或者设置缓存Cookie、Cache-Control等。此外除了标准的请求头,我们还可以自定义请求头字段塞到请求头里。

    • Host:客户端指定自己想访问的服务器的IP地址和端口号,比如Host: localhost:8080
    • User-Agent:客户端表明自己的身份,使得服务器能够识别用户使用的设备、操作系统及版本、CPU 类型等,比如Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.3 Safari/605.1.15
    • Accept:客户端告诉服务器客户端能接收什么格式的响应体,比如Accept: text/plain,text/html,text/css;q=0.9,text/javascript;q=0.9,application/json;charset=UTF-8,image/png,image/jpeg,*/*;q=0.8;(q代表优先级,默认值、最大值为1,值越大代表优先级越高,即建议服务器优先考虑给我传输这种格式以及这种编码的响应体)
    • Accept-Charset:客户端告诉服务器客户端能接收什么编码方式比如:Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7;(*代表任意)
    • Connection:客户端告诉服务器使用长连接,比如Connection: keep-alive;(HTTP/1.1下,即便没有这个请求头,也默认使用长连接)
    • Content-Type(只针对POST请求):客户端告诉服务器发送给服务器的是什么格式以及采用了什么编码方式的请求体,比如Content-Type: application/x-www-form-urlencoded
    • Content-Length(针对POST请求):客户端告诉服务器发送给服务器的请求体有多长(单位为字节),比如Content-Length: 43
    • Range:客户端告诉服务器我想拿你那部分的数据,多线程断点续传经常用,比如Range: bytes=500-999
    • Cookie:Cookie和token/ticket的作用是一样的。比如我们App里的某些接口必须得用户登录后才能访问,那如果用户不登录、直接通过浏览器去访问这些接口,服务端就会返回错误信息,这是对的就应该这样。而如果用户通过App的登录接口成功登录,此时服务器针对登录接口的响应里就会通过响应头里的Set-Cookie: JSESSIONID=666把一个唯一的标识JSESSIONID=666返回给客户端(服务端的网络三方库帮他们做了这件事),客户端会保存下来,后续用户在App里访问其它所有的接口时都会通过请求头里的Cookie字段把Cookie: JSESSIONID=666传给服务端(客户端的网络三方库帮我们做了这件事),服务端在收到来自客户端的请求时,如果发现请求头里有Cookie字段并且JSESSIONID的值能跟服务端存储的对上号,就判定为这个用户登录过,就允许访问那些必须登录后才能访问的接口,当然Cookie也是有有效时间的,这个服务端可以控制。只不过实际开发中我们没通过请求头和响应头的Cookie来做这件事,而是自己写了一套token/ticket作为接口的参数传来传去,但是他们的作用是一样的。
    • 缓存相关If-None-Match: 响应头里的ETag值——这个主要用来针对响应头里Cache-Control: no-cache时对比服务器数据和缓存数据是否有变化用;If-Modified-Since: 响应头里的Last-Modified值——这个跟If-None-Match的作用一样,主要针对上一次的响应里没有ETag值时使用,也就是没办法用If-None-Match了就用候补If-Modified-Since,其实是因为前者更准确。
    3.2 常见的响应头字段
    • Connection:服务器告诉客户端使用或者断开长连接,比如Connection: keep-alive或者Connection: close
    • Keep-Alive:服务器告诉客户端长连接会保持多长时间(单位为秒),比如Keep-Alive: timeout=20;(注意:网络三方库设置的超时时间是指到了那个时间点连TCP连接都没建立好,而不是指数据获取不完而超时,只要在超时时间内建立好了TCP连接,这个超时时间就没有意义了,那么即便你的数据要一个小时才能获取完也不会超时。网络三方库的超时时间跟这里长连接的超时时间没有半点儿关系,这里的超时时间第一个前提就是TCP连接已经成功建立、此时三方库的超时时间已经失去意义,这里的超时时间是指TCP建立好、数据传输也传输完了、TCP连接仍然会保持多长时间)
    • Content-Type:服务器告诉客户端发送给客户端的是什么格式以及采用了什么编码方式的响应体,比如Content-Type: application/x-www-form-urlencoded
    • Content-Length:服务器告诉客户端发送给客户端的响应体有多长(单位为字节),比如Content-Length: 43
    • Accept-Range:服务器告诉客户端是否支持客户端获取部分数据,比如Accept-Range: bytes代表支持,Accept-Range: none代表不支持;
    • Set-Cookie:跟请求头里的Cookie连用,详见”常见的请求头字段“部分;
    • Cache-Control:缓存是指我们把请求到的东西存储到内存中或者磁盘中。做缓存的目的是为了加快请求的响应速度,并且也可以节省用户的流量。通常当我们发一个GET请求 + 静态资源(HTML、CSS、JS、图片)的时候,就需要做缓存,具体的缓存策略(max-age:缓存的过期时间,单位为秒;no-storage:不做缓存;private:默认,只允许用户也就是我们开发者做缓存,如果本地缓存没过期,就使用本地缓存,如果本地缓存过期,就发一个请求给服务器询问数据是否有变化,有变化服务器就会返回的新数据并使用,没变化就继续使用一遍缓存;no-cache:和private一样做缓存,但是两者的区别是no-cache在做每次请求的时候会忽略本地缓存有没有过期这个判断,而总是直接发一个请求给服务器询问数据是否有变化,有变化服务器就会返回的新数据并使用,没变化才使用缓存;public:允许用户、代理服务器做缓存)就赋值给Cache-Control这个字段,也可参考SDWebImage的缓存策略来理解。
    HTTP缓存的使用流程

    4、请求体和响应体

    4.1 请求体编码/响应体编码

    国际标准化组织ISO强制规定Body里也只能出现跟URL要求一样的合法字符,非法字符都必须编码后才能出现在Body里。Body编码就不多说了,实际开发中我们很少去写Body编码的代码,这是因为现在客户端和服务端的网络三方库针对Body默认也都采用UTF-8编码,大家都默认了......如果真得决定采用别的编码方式,那就去约定吧。

    4.2 请求体格式/响应体格式

    实际开发中当我们使用POST请求的时候,要考虑一个问题,那就是”要采用什么格式把请求体发送给服务端“,常用的有三种格式:表单提交(请求头里对应的应该写Content-Type: application/x-www-form-urlencoded,AFNetworking默认)、JSON提交(请求头里对应的应该写Content-Type: application/json,Dio默认)和multipart提交(请求头里对应的应该写Content-Type: multipart/form-data; boundary=...,上传文件时必须采用这种格式),好在网络三方库已经帮我们把设置请求头、组装请求体格式这些非常非常繁琐的事情给做了,我们需要做的就是跟后台约定好要采用什么格式上传、然后调用网络三方库相应的API、把要传给服务端的入参以Map的形式扔给网络三方库就好了,比如当我们调用表单提交的API时,三方库就会在请求头里设置Content-Type: application/x-www-form-urlencoded,然后把入参组装成表单提交特有的格式,其它两种也是同理。不过可能你会发现实际开发中我们即便是在使用POST请求,但也很少去跟服务端开发人员对接到底要使用哪种格式,这是因为大家已经默认提交普通数据时采用表单提交,上传文件时采用multipart提交,响应体采用JSON提交返回,而一旦服务端真有哪个接口要求采用JSON提交、可是双方又没有提前对接、客户端继续采用了默认的表单提交,那这个POST请求就会报错,因为客户端发给服务器的数据他们解析不了,大家就一块儿去调试吧,最终会发现原来是提交格式不对。

    而使用GET请求的时候,就不需要考虑什么表单提交、JSON提交和multipart提交这些东西,因为它们三个是用来控制请求体的格式的,GET请求根本就没有请求体啊。也许你会考虑一下GET请求的URL是否编码了,但实际上也不用过虑,因为网络三方库肯定会帮我们做URL编码。

    下面就举例子看一下采用表单提交、JSON提交和multipart提交对请求体格式的影响究竟是什么,响应体的格式也是同理的,就不贴AFNetworking和Dio的源码了,以后专门分析源码的时候再说。

    • 表单提交,请求体的格式为:

    &分割请求参数,用=来分割请求参数名和请求参数值。

    AFNetworking默认采用表单提交 Wireshark抓包AFNetworking Dio采用表单提交 Wireshark抓包Dio
    • JSON提交,请求体的格式为:

    {key1: value1, key2: value2}这样key-value键值对的形式。

    AFNetworking采用JSON提交 Wireshark抓包AFNetworking Dio默认采用JSON提交 Wireshark抓包Dio
    • mutipart提交,请求体的格式为:

    --boundary
    附加信息 参数名1

    参数值1
    --boundary
    附加信息 参数名2

    参数值2
    --boundary--

    例子:

    AFNetworking采用multipart提交 Wireshark抓包AFNetworking Dio采用multipart提交 Wireshark抓包Dio

    三、HTTP的安全问题


    encrypt:加密
    decrypt:解密
    plaintext:明文
    ciphertext:密文

    HTTP默认是采用明文传输数据的,所以会有很大的安全隐患。常见的提高安全性的办法就是对传输的数据进行加密,然后再进行传输。常见的加密方式有

    参考

    1、字符编码:字符编码笔记:ASCII,Unicode 和 UTF-8
    2、各个码表的演变:Unicode 和 UTF-8 有什么区别?
    3、URL编码:URL编码
    4、URL里的保留字符:保留字符
    5、关于URL的长度限制:关于 HTTP GET/POST 请求参数长度最大值的一个理解误区
    6、头部字段:HTTP请求头与响应头
    7、Content-Type:Content-Type 详解

    相关文章

      网友评论

        本文标题:网络(三):应用层HTTP

        本文链接:https://www.haomeiwen.com/subject/atoyoltx.html