域名体系
好了,现在TCP提供可靠(数据不丢失)且字节流(数据完整性),而且也有方便我们记忆的域名,但是互联网资源千万种,也不知道访问什么(图片,文字,视频一大堆),这个时候URI(统一资源标识符)出现了,那长啥样?
URI格式
协议名:HTTP协议,另外还有ftp等协议。告知访问资源时使用什么协议。
紧接着是分隔符:"://"
主机名:标记互联网主机,可以是IP也可以是域名,如果不写端口则使用默认端口,例如HTTP为80,HTTPS为443。
登录认证信息:登录主机时的用户名密码(不建议,直接告诉了别人你的隐私信息)
主机名:此处可以是域名也可以是IP,如果不写端口号则是默认端口。比如HTTP默认端口为80,HTTPS默认端口为443。资源所在位置:资源在主机上的位置,使用“/”分隔多级目录,在这里是“/en/download.html”。注意,必须"/"开头。参数:用"?"开始,表示额外的请求要求。通常使用"key=value"的方式存在,如果多个"key=value"则使用"&"相连。看几个例子:
http://nginx.org/en/download.html
file:///E:/Demo/index/
这里注意是三个"///",因为前面"://"作为分隔符,资源路径按照"/"开头。既然规则这么多,对于接收方而言需要完成的解析也需要遵守规则,全球用户很多使用HTTP,每个国家地区所使用语言不同,HTTP为了能对其进行统一处理,引入了URI编码,方法比较简单,将非ASCII或者特殊字符全部转换为十六进制字节值,同时在前面加入"%"。比如空格被转换为" ","中国"就编码为"中国 "。3、请求体响应报文
响应报文
状态行----服务器响应的状态。
<1>版本号:使用的HTTP什么版本
<2>状态码:不同数字代表不同的结果,就如我们在编码时,通过返回不同的值代表不同的语义。
状态码一共分为5类。
1××:处于中间状态,还需后续操作
2××:成功收到报文并正确处理
"200OK":最常见的成功状态码,表示一切正常,客户端获得期许的处理结果。如果不是Head请求,那么在响应头中通常会有Body数据。"204No Content":这个的含义和"200"很相似,不同之处在于它的响应头中没有Body数据。"206Partial Content":是 HTTP 分块下载或断点续传的基础,在客户端发送“范围请求”、要求获取资源的部分数据时出现,它与 200 一样,也是服务器成功处理了请求,但Body 里的数据不是资源的全部,而是其中的一部分。状态码 206 通常还会伴随着头字段“Content-Range”,表示响应报文里 Body 数据的具体范围,供客户端确认,例如“Content-Range: bytes 0-99/5000”,意思是此次获取的是总计5000 个字节的前 100 个字节。
3××:重定向到其他资源位置
"301Moved Permanently":
“永久重定向”,意思是本地请求的资源以及不存在,使用新的URI再次访问。
“302Found”:“MovedTemporarily”,“临时重定向”,临时则所请求的资源暂时还在,但是目前需要用另一个URI访问。
301和 302 通过在字段Location中表明需要跳转的URI。两者最大的不同在于一个是临时改变,一个是永久改变。举个例子,有时候需要将网站全部升级为HTTPS,这种永久性改变就需要配置永久的"301"。有时候晚上更新系统,系统暂时不可用,可以配置"302"临时访问,此时不会做缓存优化,第二天还会访问原来的地址。
“304Not Modified”:运用于缓存控制。它用于 If-Modified-Since 等条件请求,表示资源未修改,可以理解成“重定向已到缓存的文件”(即“缓存重定向”)。
4××:请求报文有误,服务器无法处理
"400Bad Request”:通用错误码,表示请求报文有错误,但是这个错误过于笼统。不知道是客户端还是哪里的错误,所以在实际应用中,通常会返回含有明确含义的状态码。“403Forbidden”:注意了,这一个是表示服务器禁止访问资源。原因比如涉及到敏感词汇、法律禁止等。当然,如果能让客户端有一个清晰的认识,可以考虑说明拒绝的原因并返回即可。“404Not Found”:
这可能是我们都知道且都不想看到的状态码之一,它的本意是想要的资源在本地未找到从而无法提供给服务端,但是现在,只要服务器"耍脾气"就会给你返回 404,而我们也无从得知后面到底是真的未找到,还是有什么别的原因,
"405Method Not Allowed":
获取资源的方法好几种,我们可以对某些方法进行限制。例如不允许 POST 只能 GET;
"406Not Acceptable":
客户端资源无法满足客户端请求的条件,例如请求需要中文但只有英文;
"408Request Timeout":
请求超时,服务器等待了过长的时间;
"409Conflict":多个请求发生了冲突,可以理解为多线程并发时的竞态;413Request Entity Too Large:
请求报文里的 body 太大;
414Request-URI Too Long:请求行里的 URI 太大;429Too Many Requests:客户端发送了太多的请求,
通常是由于服务器的限连策略;431Request Header Fields Too Large:请求头某个字
段或总体太大;
5××:服务器错误,服务器对请求出的时候发生内部错误。
“500Internal Server Error”:
和400类似,属于一个通用的错误码,但是服务器到底是什么错误我们不得而知。其实这是好事,尽量少的将服务器资源暴露外网,尽量保证服务器的安全。
“502Bad Gateway”:通常是服务器作为网关或者代理时返回的错误码,表示服务器自身工作正常,访问后端服务器时发生了错误,但具体的错误原因也是不知道的。“503Service Unavailable”:
表示服务器当前很忙,暂时无法响应服务,我们上网时有时候遇到的“网络服务正忙,请稍后重试”的提示信息就是状态码 503。
503是一个“临时”的状态:
暂时比较忙,稍后提供服务。在响应报文中的“Retry-After”字段,指示客户端可以在多久以后再次尝试发送请求。
4、请求体上面大部分都是涉及到Header部分,还有非常重要的Body,Everybody。
头字段注意事项:
<1>字段名不区分大小写,例如“Host”也可以写成“host”,但首字母大写的可读性更好;<2>字段名里不允许出现空格,可以使用连字符“-”,但不能使用下划线"_"。例如,“test-name”是合法的字段名,而“test name”“test_name”是不正确的字段名;
<3>字段名后面必须紧接着“:”,不能有空格,而":"后的字段值前可以有多个空格;
<4>字段的顺序是没有意义的,可以任意排列不影响语义;
<5>字段原则上不能重复,除非这个字段本身的语义允许,例如 Set-Cookie。
HTTP的body常常被分为这几种的类别:
<1>text:超文本text/html,纯文本text/plain
<2>audio/video:音视频数据
<3>application: 可能是文本,也可能是二进制,交给上层应用处理
<4>image: 图像文件。image/png等
但是带宽一定,数据大了通常考虑使用压缩算法进行压缩,在HTTP中使用Encoding type表示,常用的压缩方式有下面几种:
<1>gzip:
一种数据格式,默认且目前仅使用deflate算法压缩data部分。
<2>deflate:
deflate是一种压缩算法,是huffman编码的一种加强。
<3>br:
br通过变种的LZ77算法、Huffman编码以及二阶文本建模等方式进行数据压缩,其他压缩算法相比,它有着更高的压塑压缩效率。
使用相应的压缩方法在带宽一定的情况下确实有不错的效果,但是GZIP等主要针对文件压缩效果不错,但是对视频就不行了。这个时候是不是可以使用数据结构中常用的分而治之,大化小再合并的方式呢。
文件拆分
OK,在报文中使用"Transer-Encoding:chunked"表示,代表Body部分数据是分块传输的。另外在Cody中存在一个Content-length字段表示Body的长度,两者不能共存,另外很多时候是流式数据,Body中没有指明Content-length,这个时候一般就是Chunked传输了。
现在可以通过采用分块的方式增强带宽的利用率,那他的编码规则如何呢?
<1>每一个分块包含长度和数据块
<2>长度头按照CRLF结束
<3>数据块在长度快后,且最后CRLF结尾
<4>使用长度0表示结束,"0\r\n\r\n"
我们还是看图加深印象: