[TOC]
1.Web及网络基础
1.1TCP/IP分层
TCP/TP协议族里重要的一点就是分层。TCP/IP协议族按层次分为一下4层:应用层、传输层、网络层和数据链路层。
- 应用层:应用层决定了向用户提供应用服务时通信的活动。
TCP/IP协议族内预存了各类通用的应用服务。比如,FTP和DNS服务就是其中两类,HTTP协议也处于该层
- 传输层: 传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输。(有两个性质不同的协议:TCP和UDP)
- 网络层: 用来处理在网络上流动的数据包。数据包时网络传输的最小单位。该层规定了通过怎么样的路径到达对方计算机,把数据传输给对方。
- 链路层(数据链路层): 用来处理连接网络的硬件部分,包括控制操作系统、硬件的设备驱动,网卡及光纤等物理课件部分。硬件上的范畴均在链路层的作用范围之内。
1.2TCP/TP通信传输流
利用TCP/IP协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则向应用层往上走。
以HTTP举例说明:
- 首先作为发送端的客户端在应用层发出一个想看某个web页面的HTTP请求
- 为了传输方便,传输层会将发送的数据(HTTP请求报文)分割,并在各个报文打上序号标记和端口号转发给网络层。
- 网络层增加作为通信目的地的MAC地址后转发给链路层
- 服务端的链路层收到数据后,按需往应用层发送。当传输到应用层才算真正的收到客户端发来的HTTP请求。
- 发送端在层与层之间传输数据时,经过每一层都会加上一个该层所属的信息首部。反之接受端在层与层传输数据时,每经过一层时都会把对应的首部消去(这种把数据信息包装起来的做法称之为封装)。
1.3 与HTTP关系密切的协议: IP、TCP和DNS
1.3.1 负责传输的IP协议
IP协议(这里的IP协议并不是指IP地址,位于网络层)的作用是把数据包传送给对方,而要保证确实送到对方那里,则需要知道目标的IP地址和MAC地址(MAC地址指的是网卡地址,IP地址可变,但是MAC地址是不变的。根据APR协议就能通过IP地址定位到对应的MAC地址)。
在网络上,通信双方都在同一个局域网(LAN)的情况是很少的。一般都需要经过多台计算机和网络设备中转才能连接到对方。这中间的计算机和路由器只能获取粗略的传输路线,没有人能全面掌握互联网中的传输状况。这种机制称为路由(routing)。就像快递一样,物品时通过一个个中转站,最后才能到达目的地。
1.3.2 确保可靠的TCP协议
TCP协议处于传输层,提供可靠的字节流服务
- 字节流服务:为了方便传输,将大块数据分割成以报文段(segment)为单位的数据包
- 可靠:利用三次握手策略(three-way handshaking)确保数据能到达目标
三次握手
TCP不会对传送后的情况置之不理,他一定会向对方确认是否成功到达。握手过程中使用了TCP的标志--- SYN(synchronize)和ACK(acknowleagement)。
- 发送端首先发送一个带SYN标志的数据包给对方。
- 接收端收到后,回传一个SYN/ACK标志的数据包以示传达确认信息。
- 最后,发送端再回传一个ACK标志的数据包,代表握手结束。
-
若在握手过程中某个阶段莫名中断,TCP协议会再次以相同的顺序发送相同的数据包。
1.3.3 负责域名解析的DNS服务
DNS服务是和HTTP协议一样位于应用层的协议。它提供域名到IP地址之间的解析服务。他提供域名到IP地址之间的解析服务。或者逆向从IP地址反查域名
2. 简单的HTTP协议
2.1. HTTP协议用于客户端和服务端之间的通信
在应用HTTP协议时,在一条通信线路上,必有一端是客户端一端是服务端。请求访问资源的一端是客户端,而提供资源响应的一端是服务端。两台计算机客户端和服务端的角色可能互换,但是就一条通信线路来说是固定的。(服务器之间互相调用,发起请求的一段是客户端)
2.2. 通过请求和响应的交换达成通信
客户端发出请求,服务端回复响应。
请求报文:一般包括几个内容:请求方法,请求URI, 协议版本,可选的请求首部字段(请求头 Request Header)和内容实际构成
响应报文:一般包括: 协议版本,状态码,状态码的原因短语,响应首部字段(响应头 Response Header)和实体主体构成
2.3. HTTP是不保存状态的协议(无状态协议)
HTTP每次新的请求都会对应新的响应。协议本身不会保留之前的一切的请求或者响应报文。这么设计是为了处理大量事务,确保协议的可伸缩性。
但是在我实际开发中,常常需要记住用户的身份登录状态等等。
所以HTTP1.1为了实现期望的保持状态功能,于是引入Cookie技术。当然有现在的token方案(需要客户端配合,服务端在登录之后返回一个加密的带有用户信息的token字符串,客户端收到缓存在本地,在以后所有的请求中携带上这个token,服务端相应的就可以解密这个token来判断用户的身份)
2.4. 确定资源的URI
第2点谈到了请求报文中包括URI,这样就能定位服务端的指定资源。 指定请求URI的方式有很多。
2.5. 告知服务器意图的HTTTP方法
HTTP 请求报文中指定了客户端请求的方法,常见的方法有GET、POST、PUT、DELETE等,每个方法的意图其实都是有所去别的。下面是方法说明与支持版本的表格。
2.6. 持久连接节省通信量
HTTP协议的初始版本中,每进行一次HTTP通信都要断开一次TCP连接。
随着计算机的发展请求的内容以及数量大大增加(随便一个页面都有很多的图片以及其它资源请求),因此,每次请求都会造成无谓的TCP连接建立与断开,增加通信量的开销。
为了解决这个问题提出了持久连接
持久连接
为了解决上面的问题,HTTP/1.1和一部分的1.0想出了持久连接(HTTP keep-alive)方法。只要任意一端没有提出断开连接,则保持TCP连接状态。这样就可以避免重复建立连接和断开连接带来的额外开销,Web页面的显示速度就提高了
HTTP/1.1默认所有的连接都是持久连接
管线化
持久化连接使得多数请求以管线化(pipelining)方式发送成为可能。以前发送请求后需要等待响应才能发送一个请求。
并发请求,一个请求发出后无需等待响应就可以直接发送下一个请求。
2.7. 使用Cookie的状态管理
前面说了HTTP是无状态协议,这么设计不保存状态减轻了服务器的CPU及内存资源的消耗。如果需要状态就需要在每次的请求报文中附加参数来管理状态。前面提到了HTTP/1.1引入了Cookie技术。
Cookie技术通过在请求和响应报文中写入Cookie信息来控制客户端的状态。Cookie会根据服务端发送的响应报文内的一个叫做Set-Cookie的首部字段信息,通知客户端保存Cookie。当下次客户端发送请求时,请求报文中自动加入Cookie发送出去。
3.HTTP报文内的HTTP信息
3.1 HTTP报文
HTTP协议交互的信息HTTP报文,客户端解和服务端的报文分别叫请求报文和响应报文。
HTTP报文本身是由多行数据(用CR+LF作换行符)构成的字符串文本
3.2 请求报文及响应报文的结构
- 请求行: 包含用于请求的方法,请求URI和HTTP版本
- 状态行: 包含表明响应结果的状态码,原因短语和HTTP版本
- 首部字段: 包含请求和相应的各种条件和属性的各类首部。一般有4种首部:通用首部, 请求首部、响应首部和实体首部
- 其它: 可能包含HTTP的RFC(草案)里未定义的首部(Cookie等)
3.3 编码提升传输速率
HTTP在传输数据时可以按照数据原貌直接传输,也可以在传输过程中通过编码提升传输效率。
- 压缩传输的内容编码:指明实体内容的编码格式,客户端接收后按编码格式解码,常用的内容编码有
- gzip(GNU zip)
- compress(Unix系统的标准压缩)
- deflate(zlib)
- identity (不进行编码)
- 分割发送的分块传输编码: HTTP通信过程中,请求的资源时体尚未全部传输完成之前,浏览器无法显示请求页面,通过把数据分割成对快,能够让浏览器逐步显示页面。
分块传输编码会将主体分成多个部分(块)。每一块都会用16进制来标记块的大小,而主体的最后一块会使用‘0(CR+LF)’来标记
3.4 发送多种数据的多部份对象集合(multipart/xx)
发送邮件时可以发送多种不同类型的文件。是因为MIME扩展中使用一种称为多部份对象集合(multipart)的方法。HTTP中也采纳了这种方法(一般像表单提交时,就是常常包含了字段以及文件)。
多部份对象集合包含的对象如下:
-
multipart/form-data:: 在WEB表单文件上传时使用
-
multipart/byteranges:: 状态码206(Partial Content, 部分内容),响应报文包含了多个范围的内容时使用。请求部分范围的数据。
使用boundary字符串来划分多部分对象集合指明的各类实体。每个实体的起始行插入'--'+boundary
的标记,而在多部份对象集合结束的尾部地方插入'--'+boundray+'--'
的标记标志结束。
3.5 获取部分内容的范围请求
起初,当网速不好时,在下载一个大的文件过程中出现网络中断的情况就必须重新开始。为了解决这个问题,就需要一种可以恢复下载的机制,也就是从中断处恢复下载。
实现该功能就需要指定下载的实体范围。像这样指定范围发送的请求就叫做范围请求。
使用首部字段Range指定资源的byte范围。 返回的状态码为206.部分内容。如果服务端无法响应方位请求,则会返回状态码为200的完整实体内容
3.6 内容协商返回最合适的内容
有时候访问同一个地址,但是返回的内容不一样。当浏览器默认的语言为英文或者中文,则会显示对应的英文版或者中文版的Web页面,这种机制称为内容协商(Content Negotiarion)。
包含在请求报文中的某些首部字段就是判断的基准。如下:
- Accept
- Accept-Charset
- Accept-Encoding
- Accept-Language
- Content-Language
内容协商技术有一下三种: - 服务端驱动协商:服务端根据请求的首部字段为参考,在服务端自行处理。但对用户来说,以浏览器发送的信息为为依据(一般时浏览器设置的语啊言等),不一定能筛选出最符合用户的内容
- 客户端驱动协商: 有客户端进行内容协商,用户从客户端页面显示可选的列表中手动选择。也可以用js脚本在页面上自动进行选择。比如根据设备信息自动选择显示PC版页面或者H5页面
- 透明协商:由服务器驱动和客户端驱动的结合体。
4. 返回结果的HTTP状态码
状态码的职责是描述返回的请求结果,借助状态码,用户可以知道服务器端是正常处理了请求还是出现了错误
状态码如 200 OK
由三位数字和原因短语组成
数字中的第一位指定了响应的类别,响应类别有一下5种:
仅仅记录在RFC2616上的状态码就有40种。这里就介绍常用的14个状态码
1. 200 OK 请求正常处理
2.204 No Content 请求处理成功,但没有资源可以返回
一般在只需要从客户端往服务端发送消息,而对客户端不需要发送新信息内容的情况下使用。
3. 206 Partial Content 客户端范围请求,返回部分内容
**4.301 Moved Permanently ** 永久重定向
该状态码表示请求的资源已经被分配了新的URI,以后应使用资源现在所指的URI,新的URI地址为Loacation首部提示的URI。
测试请求http://ymm56.com ,可以看到响应报文如下:
5. 302 Found 临时移动
该状态码表示请求的资源已经分配新的URI, 希望用户(本次)使用新的URI访问,与301状态码相似,区别就是一个是永久的一个是临时的。以保存书签为例,如果遇到301则需要更新书签,302则不用。
** 6.303 See Other** 查看其它位置,应当使用GET方法获取资源
表示由于请求对应的资源存在着另一个URI,应使用GET方法获取请求的资源。与302 状态码有相同的功能,但是303状态码明确表示客户端应采用GET方法获取资源
当301, 302,303响应状态码返回时,几乎所有的浏览器都会把POST改成GET,并删除请求报文内的主体,之后请求自动再次发送。
301 302标准是禁止将POST方法改成GET, 然并卵,实际使用时大家都会这么做
7. Not Modified : 服务端资源没有改动,使用客户端缓未过期的缓存
改状态码表示客户端发送附带条件的请求时,服务端允许请求访问资源,但因发生请求未满足条件后,直接返回304 Not Modified(服务器端资源未改变,可直接使用客户端未过期的缓存)。304虽然被规划到3XX,但是与重定向没有关系。
附带条件的请求:指的是请求采用GET方法的请求报文中包含:
If-Match
、If-Modified-Since、If-None-Match
、If-Range、If-Unmodified-Since
中任一首部。这里其实就是协商缓存,后面讲首部的时候应该会讲到)
8. 307 Temporary Redirect: 临时重定向
该状态码与302 有着相同的含义。尽管302标准禁止POST变换成GET,但是大家实际使用时并不遵守。 307会遵照浏览器标准,不会从POST变成GET。 但是,对于处理相应时的行为,每种浏览器有可能出现不同的情况。
9. 400 Bad Request: 错误请求
该状态码表示请求报文中存在语法错误,服务端无法解析。错误发生时,客户端需要修改请求后再次发送请求。另外,浏览器会像200 OK 一样对待该状态码。
10. 401 Unauthorized:未认证
该状态码表示发送的请求需要通过HTTP认证的认证信息,一般指用户需要登录,或者登录失败
11. 403 Forbidden: 权限不够
该状态码表示用户的权限不够,无法访问该资源。服务端没有必要给出拒绝的详细理由,如果想要做说明的话可以在主体部分对原因进行描述。
12. 404 Not Found: 资源不存在
13. 405 Method Not Allowd: 方法不允许,表示请求方法错误
14. 500 Internal Server Error: 服务端内部错误
该状态码表示服务端在执行请求时出现错误,可能存在bug或者临时故障
15. 503 Service Unavaliable: 服务不可用
该状态码表示服务器暂时处于超负荷状态或者停机维护,现在无法处理请求。如果事先得知解除以上状况需要的时间,最好写入Retry-After首部字段返回给客户端
上面说明的状态码都是HTTP规范的,但是实际开发中,很多服务端相应的状态码并不会按照这个来。比如很多web程序,内部发生了错误,返回的状态码都是200 OK,在返回实体的主体中描述错误的原因,这种情况也是很常的。
5. 与HTTP协作的Web服务器
一台Web服务器可以搭建多个独立域名的Web网站, 也可作为通信路径上的中转服务提升传输效率
5.1 使用单台虚拟主机实现多个域名
一台主体只有一个IP, 但是多个域名可以指向同一个IP. 所以可以使用一台服务器托管多个Web服务。这就是利用了虚拟主机的功能
我个人的理解就是如果有两个域名指向了同一个服务器,但服务器需要提供两个不同的服务,则服务器需要根据域名创建不同的虚拟主机提供不同的服务,相当与Nginx中的配置多个Server绑定80端口,然后用server_name指定不同的域名地址来区分两个不同的服务。
5.2 通信数据转发程序: 代理、网关、隧道
HTTP通信时,除客户端和服务器外,还有一些用于通信数据转发的应用程序,例如代理、网关和隧道。
这些应用程序和服务器可以将请求转发给通信线路上的下一站服务器,并能接受服务端响应的数据再转发给客户端。
5.2.1 代理
代理服务器的基本行为就是接受客户端的请求后转发给其它服务器。代理不改变请求的URI,会直接发送给前方只有资源的目标服务器,从目标服务器返回的响应也会经过代理服务器返回给客户端。 代理服务器可以串联。
代理使用的理由有: 利用缓存技术介绍网络带宽、对内部特定网站的访问控制等等
代理按两种基类分类: 是否使用缓存和是否修改报文
- 缓存代理:代理转发响应式,缓存代理会预先将资源的副本保存在代理服务器上,当再次接受到对相同资源的请求时,通过判断就可以不经过源服务器直接响应之前缓存的内容。
- 透明代理: 不修改请求报文的代理称为透明代理,反之则是非透明代理
5.2.2 网关
网关的工作机制和代理非常相似,但是网关能时通信线路上的服务器提供非HTTP协议服务。
利用网关能提高通信的安全性: 可以再客户端和网关之间的通信线路上加密以确保连接的安全。比如,网关也可以连接数据库,使用SQL语句查询数据。另外在Web购物网站进行信用卡核算时,网关可以和信用卡结算系统联动。 (网关没有使用过,后期可以配合nginx测试下网关的使用)
5.2.3 隧道
隧道可按要求建立起一条与其它服务器的通信线路,可以使用SSL等加密手段进行通信。隧道的目的是确保客户端能与服务器进行安全的通信。