文章目录
- 1.网络概述
- 2.TCP协议
- 2.1.TCP的特性
- 2.2.TCP通讯时序图
- 2.3.TCP的三次握手
- 2.4.TCP 数据通信
- 2.5.TCP的四次挥手
- 2.6.TCP的状态转换
- 2.7.TCP KeepAlive
- 2.8.SYN攻击
- 3.UDP协议
- 4.HTTP协议
- 4.1.HTTP的特性
- 4.2.HTTP的注意事项
- 4.3.HTTP报文
- 4.4.条件GET
- 4.5.持久连接/连接重用
- 4.6.Transfer-Encoding
- 4.7.HTTP Pipelining(HTTP 管线化)
- 4.8.会话跟踪
- 4.9.跨站请求伪造/攻击CSRF(Cross-Site Request Forgery)
- 4.10.XSS(Cross Site Scripting,跨站脚本攻击)
- 4.11.浏览器输入一个URL的过程
- 5.HTTPS
- 6.HTTP2
- 7.WebSocket
- 8.RESTful
- 9.RPC(Remote Procedure Call远程过程调用)协议
- 10.gRPC
1.网络概述
1.1.协议
协议,网络协议的简称,网络协议是通信计算机双方必须共同遵从的一组约定,是为了使数据在网络上从源到达目的,网络通信的参与方必须遵循相同的规则,这套规则称为协议(protocol),它最终体现为在网络上传输的数据包的格式,其三要素是:语法、语义、时序。协议往往分成几个层次进行定义,分层定义是为了使某一层协议的改变不影响其他层次的协议。
1.2.协议的特点
- 协议中的每个人都必须了解协议,并且预先知道所要完成的所有的步骤。
- 协议中的每个人都必须同意并遵循它。
- 协议必须是清楚的,每一步必须明确定义,并且不会引起误解。
1.3.协议释义
从应用的角度出发,协议可理解为“规则”,是数据传输和数据的解释的规则。假设,A、B双方欲传输文件。规定:
第一次,传输文件名,接收方接收到文件名,应答OK给传输方;
第二次,发送文件的尺寸,接收方接收到该数据再次应答一个OK;
第三次,传输文件内容。同样,接收方接收数据完成后应答OK表示文件内容接收成功。
由此,无论A、B之间传递何种文件,都是通过三次数据传输来完成。A、B之间形成了一个最简单的数据传输规则。双方都按此规则发送、接收数据。A、B之间达成的这个相互遵守的规则即为协议。
这种仅在A、B之间被遵守的协议称之为原始协议。
当此协议被更多的人采用,不断的增加、改进、维护、完善。最终形成一个稳定的、完整的文件传输协议,被广泛应用于各种文件传输过程中。该协议就成为一个标准协议。最早的ftp协议就是由此衍生而来。
1.4.典型协议
网络层级 | 常见协议 |
---|---|
应用层 | 常见的协议有HTTP协议,FTP协议。 |
传输层 | 常见协议有TCP/UDP协议。 |
网络层 | 常见协议有IP协议、ICMP协议、IGMP协议。 |
链路层 | 常见协议有ARP协议、RARP协议。 |
协议名称 | 协议特性 |
---|---|
TCP | TCP传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。 |
UDP | UDP用户数据报协议(User Datagram Protocol)是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单、不可靠的信息传送服务。 |
HTTP | HTTP超文本传输协议(Hyper Text Transfer Protocol)是互联网上应用最为广泛的一种网络协议 |
FTP | FTP文件传输协议(File Transfer Protocol) |
IP | IP协议是因特网互联协议(Internet Protocol) |
ICMP | ICMP协议是Internet控制报文协议(Internet Control Message Protocol)它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。 |
IGMP | IGMP协议是 Internet 组管理协议(Internet Group Management Protocol),是因特网协议家族中的一个组播协议。该协议运行在主机和组播路由器之间 |
ARP | ARP协议是正向地址解析协议(Address Resolution Protocol),通过已知的IP,寻找对应主机的MAC地址 |
RARP | RARP是反向地址转换协议,通过MAC地址确定IP地址 |
1.5.分层模型
1.5.1.网络分层架构
为了减少协议设计的复杂性,大多数网络模型均采用分层的方式来组织。每一层都有自己的功能,就像建筑物一样,每一层都靠下一层支持。每一层利用下一层提供的服务来为上一层提供服务,本层服务的实现细节对上层屏蔽。
越下面的层,越靠近硬件;越上面的层,越靠近用户。
业内普遍的分层方式有两种。OSI七层模型 和TCP/IP四层模型。
OSI七层模型:物、数、网、传、会、表、应
TCP/IP四层模型:链、网、传、应
序号 | 层次名称 | 概述 |
---|---|---|
1 | 物理层 | 是计算机网络OSI模型中最低的一层,主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后再转化为1、0,也就是我们常说的数模转换与模数转换),物理层的数据叫做比特 |
2 | 数据链路层 | 定义了如何让格式化数据以帧为单位进行传输,以及如何让控制对物理介质的访问。这一层通常还提供错误检测和纠正,以确保数据的可靠传输。如:串口通信中使用到的115200、8、N、1 |
3 | 网络层 | 在位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择。Internet的发展使得从世界各站点访问信息的用户数大大增加,而网络层正是管理这种连接的层。 |
4 | 传输层 | 定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把传输层的数据叫做段。 |
5 | 会话层 | 通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)。 |
6 | 表示层 | 可确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。例如,PC程序与另一台计算机进行通信,其中一台计算机使用扩展二一十进制交换码(EBCDIC),而另一台则使用美国信息交换标准码(ASCII)来表示相同的字符。如有必要,表示层会通过使用一种通格式来实现多种数据格式之间的转换。 |
7 | 应用层 | 是最靠近用户的OSI层。这一层为用户的应用程序(例如电子邮件、文件传输和终端仿真)提供网络服务 |
1.5.2.层与协议
网络的每一层,都定义了很多协议。这些协议的总称,叫“TCP/IP协议”。TCP/IP协议是一个大家族,不仅仅只有TCP和IP协议,它还包括其它的协议,如下图:
1.6.各层功能
1.链路层
**以太网规定,连入网络的所有设备,都必须具有“网卡”接口。数据包必须是从一块网卡,传送到另一块网卡。**通过网卡能够使不同的计算机之间连接,从而完成数据通信等功能。网卡的地址——MAC地址,就是数据包的物理发送地址和物理接收地址。
2.网络层
网络层的作用是引进一套新的地址,使得我们能够区分不同的计算机是否属于同一个子网络。这套地址就叫做“网络地址”,就是我们平时所说的IP地址。这个IP地址好比我们的手机号码,通过手机号码可以得到用户所在的归属地。
网络地址帮助我们确定计算机所在的子网络,MAC 地址则将数据包送到该子网络中的目标网卡。网络层协议包含的主要信息是源IP和目的IP。
于是,“网络层”出现以后,每台计算机有了两种地址,一种是 MAC 地址,另一种是网络地址。两种地址之间没有任何联系,MAC 地址是绑定在网卡上的,网络地址则是管理员分配的,它们只是随机组合在一起。
网络地址帮助我们确定计算机所在的子网络,MAC 地址则将数据包送到该子网络中的目标网卡。因此,从逻辑上可以推断,必定是先处理网络地址,然后再处理 MAC 地址。
3.传输层
当一边聊QQ,一边聊微信,当一个数据包从互联网上发来的时候,怎么知道它是来自QQ的内容,还是来自微信的内容?
故而,还需要一个参数,表示这个数据包到底供哪个程序(进程)使用。这个参数就叫做“端口”(port),它其实是每一个使用网卡的程序的编号。每个数据包都发到主机的特定端口,所以不同的程序就能取到自己所需要的数据。
端口特点:
对于同一个端口,在不同系统中对应着不同的进程
对于同一个系统,一个端口只能被一个进程拥有
4.应用层
应用程序收到“传输层”的数据,接下来就要进行解读。由于互联网是开放架构,数据来源五花八门,必须事先规定好格式,否则根本无法解读。“应用层”的作用,就是规定应用程序的数据格式。
1.7.通信过程
2.TCP协议
2.1.TCP的特性
- TCP 提供一种面向连接的、可靠的字节流服务
- 在一个 TCP 连接中,仅有两方进行彼此通信,广播和多播不能用于 TCP
- TCP 使用校验和,确认和重传机制来保证可靠传输
- TCP 给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复
- TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制
注意
TCP 并不能保证数据一定会被对方接收到,因为这是不可能的。TCP 能够做到的是,如果有可能,就把数据递送到接收方,否则就(通过放弃重传并且中断连接这一手段)通知用户。因此准确说 TCP 也不是 100% 可靠的协议,它所能提供的是数据的可靠递送或故障的可靠通知。
2.2.TCP通讯时序图
TCP通讯的时序图。TCP连接建立断开。包含三次握手和四次握手。
在图中,首先客户端主动发起连接、发送请求,然后服务器端响应请求,然后客户端主动关闭连接。两条竖线表示通讯的两端,从上到下表示时间的先后顺序。
注意:数据从一端传到网络的另一端也需要时间,所以图中的箭头都是斜的。
2.3.TCP的三次握手
2.3.1.三次握手
所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。
2.3.2.目的
连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换TCP 窗口大小信息。在 socket 编程中,客户端执行 connect() 时,将触发三次握手。
2.3.3.建立连接(三次握手)的过程
- 1.主动建立连接请求端(客户端), 发送 SYN 标志位, 携带 序号
客户端发送一个带SYN标志的TCP报文到服务器。这是TCP通讯时序图中三次握手过程中的段1。客户端发出SYN位表示连接请求。序号是1000,这个序号在网络通讯中用作临时的地址,每发一个数据字节,这个序号要加1,这样在接收端可以根据序号排出数据包的正确顺序,也可以发现丢包的情况。
另外,规定SYN位和FIN位也要占一个序号,这次虽然没发数据,但是由于发了SYN位,因此下次再发送应该用序号1001。
mss表示最大段尺寸,如果一个段太大,封装成帧后超过了链路层的最大长度,就必须在IP层分片,为了避免这种情况,客户端声明自己的最大段尺寸,建议服务器端发来的段不要超过这个长度。
- 2.被动接受连接请求端(服务器), 接收 SYN 标志,回发 ACK 携带 确认序号, 同时 发送 SYN 标志位, 携带 序号
服务器端回应客户端,是三次握手中的第2个报文段,同时带ACK标志和SYN标志。表示对刚才客户端SYN的回应;同时又发送SYN给客户端,询问客户端是否准备好进行数据通讯。
服务器发出段2,也带有SYN位,同时置ACK位表示确认,确认序号是1001,表示“我接收到序号1000及其以前所有的段,请你下次发送序号为1001的段”,也就是应答了客户端的连接请求,同时也给客户端发出一个连接请求,同时声明最大尺寸为1024。
- 3.主动建立连接请求端(客户端), 接收 SYN 标志, 回发 ACK 携带 确认序号。 —— 标志 3 次握手完成
客户必须再次回应服务器端一个ACK报文,这是报文段3。
客户端发出段3,对服务器的连接请求进行应答,确认序号是8001。在这个过程中,客户端和服务器分别给对方发了连接请求,也应答了对方的连接请求,其中服务器的请求和应答在一个段中发出。
客户端发起连接请求,携带SYN标志位、序号、数据大小【0字节】
服务端响应客户端的连接请求,携带ACK标志位,确认序号【客户端请求序号+1】,同时向客户端发起连接请求,携带SYN标志位、序号、数据大小【0字节】
客户端响应请求,携带ACK标志位,确认序号【服务端请求序号+1】
三次握手完成,对应于socket编程的client的Dial( )函数返回,server端的Accept( )函数返回
因此一共有三个段用于建立连接,称为三次握手。在建立连接的同时,双方协商了一些信息,例如,双方发送序号的初始值、最大段尺寸等。
2.4.TCP 数据通信
2.4.1.数据通信过程
- 1.客户端发出段4,包含从序号1001开始的20个字节数据
发送端发送数据同时携带序号。 - 2.服务器发出段5,确认序号为1021,对序号为1001-1020的数据表示确认收到,同时请求发送序号1021开始的数据,服务器在应答的同时也向客户端发送从序号8001开始的10个字节数据。
接收端接收数据后需要给发送端发送 ACK 应答以及确认序号 (回执),确保TCP通信模式下,数据可靠的传输。。 - 3.客户端发出段6,对服务器发来的序号为8001-8010的数据表示确认收到,请求发送序号8011开始的数据。
2.4.2.滑动窗口概念
滑动窗口:实时通知对端,本端存储数据的缓冲区大小。
在数据传输过程中,ACK和确认序号是非常重要的,应用程序交给TCP协议发送的数据会暂存在TCP层的发送缓冲区中,发出数据包给对方之后,只有收到对方应答的ACK段才知道该数据包确实发到了对方,可以从发送缓冲区中释放掉了,如果因为网络故障丢失了数据包或者丢失了对方发回的ACK段,经过等待超时后TCP协议自动将发送缓冲区中的数据包重发。
注意
数据传输中的是否丢包,与选择哪一种通信方式无关,和当前的网络环境有关系,所以说选择TCP通信方式进行数据传输一定不会丢包的说法是错误的。
2.5.TCP的四次挥手
2.5.1.四次挥手
TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),也叫做改进的三次握手,指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。客户端或服务器均可主动发起挥手动作,在 socket 编程中,任何一方执行 close() 操作即可产生挥手操作。
2.5.2.关闭连接(四次挥手)的过程
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
- 1.客户端发出段7,FIN位表示关闭连接的请求。
- 2.服务器发出段8,应答客户端的关闭连接请求。
- 3.服务器发出段9,其中也包含FIN位,向客户端发送关闭连接请求。
- 4.客户端发出段10,应答服务器的关闭连接请求。
建立连接的过程是三次握手,而关闭连接通常需要4个段,服务器的应答和关闭连接请求通常不合并在一个段中,因为有连接半关闭的情况,这种情况下客户端关闭连接之后就不能再发送数据给服务器了,但是服务器还可以发送数据给客户端,直到服务器也关闭连接为止。
2.6.TCP的状态转换
2.6.1.TCP的状态转换图
TCP状态图对排除和定位网络或系统故障时非常有帮助,总共有11中状态。
CLOSED:表示初始状态。
LISTEN:该状态表示服务器端的某个SOCKET处于监听状态,可以接受连接。
SYN_SENT:这个状态与SYN_RCVD遥相呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,随即进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。
SYN_RCVD: 该状态表示接收到SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂。此种状态时,当收到客户端的ACK报文后,会进入到ESTABLISHED状态。
ESTABLISHED:表示连接已经建立。
FIN_WAIT_1: FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。区别是:
FIN_WAIT_1状态是当socket在ESTABLISHED状态时,想主动关闭连接,向对方发送了FIN报文,此时该socket进入到FIN_WAIT_1状态。
FIN_WAIT_2状态是当对方回应ACK后,该socket进入到FIN_WAIT_2状态,正常情况下,对方应马上回应ACK报文,所以FIN_WAIT_1状态一般较难见到,而FIN_WAIT_2状态可用netstat看到。
FIN_WAIT_2:主动关闭链接的一方,发出FIN收到ACK以后进入该状态。称之为半连接或半关闭状态。该状态下的socket只能接收数据,不能发。
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,等2MSL后即可回到CLOSED可用状态。如果FIN_WAIT_1状态下,收到对方同时带 FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
CLOSING: 这种状态较特殊,属于一种较罕见的状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
CLOSE_WAIT: 此种状态表示在等待关闭。当对方关闭一个SOCKET后发送FIN报文给自己,系统会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,察看是否还有数据发送给对方,如果没有可以 close这个SOCKET,发送FIN报文给对方,即关闭连接。所以在CLOSE_WAIT状态下,需要关闭连接。
LAST_ACK: 该状态是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,即可以进入到CLOSED可用状态。
2MSL (Maximum Segment Lifetime) 和与之对应的TIME_WAIT状态,可以让4次握手关闭流程更加可靠。4次握手的最后一个ACK是是由主动关闭方发送出去的,若这个ACK丢失,被动关闭方会再次发一个FIN过来。若主动关闭方能够保持一个2MSL的TIME_WAIT状态,则有更大的机会让丢失的ACK被再次发送出去。注意,TIME_WAIT状态一定出现在主动关闭这一方。
2.6.2.状态转换详解
TCP 状态转换图:
主动连接端(客户端):
CLOSED --> 发送 SYN --> SYN_SENT --> 接收 ACK、SYN,发送 ACK --> ESTABLISHED --> 数据通信
主动关闭端(客户端):
ESTABLISHED --> 发送 FIN --> FIN_WAIT_1 --> 接收 ACK --> FIN_WAIT_2 (半关闭) --> 接收FIN,发送 ACK --> TIME_WAIT --> 等待 2MSL 时长 --> CLOSED
—— FIN_WAIT_2、TIME_WAIT、2MSL 只出现 主动端。
被动连接端(服务器):
CLOSED --> LISTEN --> 接收SYN, 发送 ACK, SYN --> SYN_RCVD --> 接收 ACK–>>ESTABLISHED --> 数据通信
被动关闭端(服务器):
ESTABLISHED --> 接收 FIN, 发送ACK --> CLOSE_WAIT (对应主动端的 FIN_WAIT_2) --> 发送 FIN --> LAST_ACK --> 接收 ACK --> CLOSED
2.7.TCP KeepAlive
TCP 的连接,实际上是一种纯软件层面的概念,在物理层面并没有“连接”这种概念。TCP 通信双方建立交互的连接,但是并不是一直存在数据交互,有些连接会在数据交互完毕后,主动释放连接,而有些不会。在长时间无数据交互的时间段内,交互双方都有可能出现掉电、死机、异常重启等各种意外,当这些意外发生之后,这些 TCP 连接并未来得及正常释放,在软件层面上,连接的另一方并不知道对端的情况,它会一直维护这个连接,长时间的积累会导致非常多的半打开连接,造成端系统资源的消耗和浪费,为了解决这个问题,在传输层可以利用 TCP 的 KeepAlive 机制实现来实现。主流的操作系统基本都在内核里支持了这个特性。
TCP KeepAlive 的基本原理是,隔一段时间给连接对端发送一个探测包,如果收到对方回应的ACK,则认为连接还是存活的,在超过一定重试次数之后还是没有收到对方的回应,则丢弃该 TCP连接。
TCP KeepAlive 的局限。首先 TCP KeepAlive 监测的方式是发送一个 probe包,会给网络带来额外的流量,另外 TCP KeepAlive 只能在内核层级监测连接的存活与否,而连接的存活不一定代表服务的可用。例如当一个服务器 CPU 进程服务器占用达到 100%,已经卡死不能响应请求了,此时 TCP KeepAlive 依然会认为连接是存活的。因此 TCP KeepAlive 对于应用层程序的价值是相对较小的。需要做连接保活的应用层程序,例如 QQ,往往会在应用层实现自己的心跳功能。
2.8.SYN攻击
2.8.1.什么是 SYN 攻击(SYN Flood)
在三次握手过程中,服务器发送 SYN-ACK 之后,收到客户端的 ACK 之前的 TCP 连接称为半连接(half-open connect)。此时服务器处于 SYN_RCVD 状态。当收到 ACK 后,服务器才能转入ESTABLISHED 状态.
SYN 攻击指的是,攻击客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送SYN包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。
SYN 攻击是一种典型的 DoS/DDoS 攻击。
2.8.2.如何检测 SYN 攻击
检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。在 Linux/Unix 上可以使用系统自带的 netstats命令来检测 SYN 攻击。
2.8.3.如何防御 SYN 攻击
SYN攻击不能完全被阻止,除非将TCP协议重新设计。我们所做的是尽可能的减轻SYN攻击的危害,常见的防御 SYN 攻击的方法有如下几种:
- 1.缩短超时(SYN Timeout)时间
- 2.增加最大半连接数
- 3.过滤网关防护
- 4.SYN cookies技术
3.UDP协议
3.1.UDP协议的特性
UDP 是一个简单的传输层协议。
- UDP 缺乏可靠性。UDP 本身不提供确认,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次。
- UDP 数据报是有长度的。每个 UDP 数据报都有长度,如果一个数据报正确地到达目的地,那么该数据报的长度将随数据一起传递给接收方。而 TCP 是一个字节流协议,没有任何(协议上的)记录边界。
- UDP 是无连接的。UDP 客户和服务器之前不必存在长期的关系。UDP 发送数据报之前也不需要经过握手创建连接的过程。
- UDP 支持多播和广播。
3.2.UDP和TCP协议的区别
TCP | UDP |
---|---|
面向连接 | 面向无连接 |
要求系统资源较多 | 要求系统资源较少 |
TCP程序结构较复杂 | UDP程序结构较简单 |
使用流式 | 使用数据包式 |
保证数据准确性 | 不保证数据准确性 |
保证数据顺序 | 不保证数据顺序 |
通讯速度较慢 | 通讯速度较快 |
3.3.UDP和TCP协议的优缺点
协议 | 优点 | 缺点 |
---|---|---|
TCP | (顺序、速度)稳定、可靠 | 系统占用资源多、发送速度慢、开发难度大 |
UDP | 系统占用少、发送速度快、开发难度小 | (顺序、速度)不稳定、不可靠 |
3.4.UDP和TCP协议的使用场景
协议 | 使用场景 |
---|---|
TCP | 对数据稳定、准确性要求较高的场合,例如:上传、下载 |
UDP | 对数据的传输速度要求较高的场合,允许适当的数据丢失,例如:直播、游戏、视频、在线电话 |
综上:
TCP:面向连接的可靠的数据包传递。 针对不稳定的网络层做完全弥补。—— 借助回执,丢包重传。
UDP:无连接的不可靠的报文传输。 针对不稳定的网络层直接还原真实状态。 —— 丢包,不处理理。
4.HTTP协议
HTTP(HyperText Transfer Protocol)超文本传输协议,是互联网上应用最为广泛的一种网络传输协议,详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传输万维网文档数据的传输协议。
HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
4.1.HTTP的特性
- HTTP构建于TCP/IP协议之上,默认端口号是80
- HTTP是无连接、无状态的
- HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。
- Web服务器根据接收到的请求后,向客户端发送响应信息。
4.2.HTTP的注意事项
- HTTP是无连接:
无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。- HTTP是媒体独立的:
只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型【MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型】。- HTTP是无状态:
HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
4.3.HTTP报文
4.3.1.请求报文
HTTP协议是以ASCII码传输,建立在TCP/IP协议之上的应用层规范,HTTP请求分为:请求行、请求头 、空行、请求包体。
1.请求行
请求行:请求方法、URL字段、协议版本
GET / HTTP/1.1
HTTP定义了与服务器交互的交互的方法【共9个】:
HTTP/0.9:
已过时。只接受 GET 一种请求方法,没有在通讯中指定版本号,且不支持请求头。由于该版本不支持 POST 方法,所以客户端无法向服务器传递太多信息。
HTTP/1.0:
第一个在通讯中指定版本号的HTTP 协议版本,至今仍被广泛采用,特别是在代理服务器中。
HTTP/1.1:
持久连接被默认采用,并能很好地配合代理服务器工作。还支持以管道方式同时发送多个请求,以便降低线路负载,提高传输速度。
HTTP/1.1相较于 HTTP/1.0 协议的主要区别:
1. 缓存处理
2. 带宽优化及网络连接的使用
3. 错误通知的管理
4. 消息在网络中的发送
5. 互联网地址的维护
6. 安全性及完整性
HTTP0.9 只有一个GET命令,没有header等描述数据的信息,服务器发送完毕就关闭TCP连接
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
实际开发工作中:一般将POST, DELETE, PUT , GET认为是对资源的增、删、改、查操作
序号 | 请求方式 | 说明 |
---|---|---|
1 | GET | 请求指定的页面信息,并返回实体主体。【安全且幂等】 |
2 | HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头,不返回文档主体。【安全且幂等】 |
3 | POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件),数据被包含在请求体中,POST 请求可能会导致新的资源的建立或已有资源的修改。 |
4 | PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
5 | PATCH | 对PUT方法的补充,用来对已知的资源进行局部更新。 |
6 | DELETE | 请求服务器删除指定的页面。 |
7 | OPTIONS | 查看服务器支持的 HTTP 方法;查看服务器的性能。对可能对服务器数据产生副作用【回退是否有害】的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型【MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型】的 POST 请求),浏览器必须首先使用 OPTIONS 发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。 |
8 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
9 | CONNECT | HTTP/1.1协议中预留给能够将连接改为 Pipeline管道方式的代理服务器。把请求连接转换到透明的 TCP/IP 通道。 |
1.GET请求方式
GET请求:
GET / HTTP/1.1
1.功能:信息的获取【安全且幂等】
特点 | 说明 |
---|---|
安全 | GET操作用于获取信息,而非修改信息,仅仅是获取资源信息,不会修改、增加数据,不会影响资源的状态。 |
幂等 | GET操作的幂等意味着对同一个URL的多个请求应该返回同样的结果。 |
2.功能:数据提交
1.可提交的数据量小,4kb左右(不同浏览器会有差异)---->受到URL长度的限制【HTTP协议规范没有对URL的长度进行限制,URL长度的限制是特定的浏览器和特定的服务器进行限制的】;
2.在URL后面拼接参数,只能以【文本】的形式传递参数。
3.安全性低,会将信息显示在地址栏。
4.速度快,通常用于对安全性要求不高的请求。
3.注意
- GET 请求可被缓存,请求参数会被完整保留在浏览器历史记录里
- GET 请求可被收藏为书签
- GET 的参数直接暴露在URL上,不应在处理敏感数据时使用
- GET 请求在URL中传送的参数是有长度限制的
- GET 请求只应当用于取回数据
- GET 参数通过URL传递,且只能以【文本】的形式传递参数
- GET 请求只能进行url编码
- GET 在浏览器回退时是无害的【无副作用】,如果有缓存不会产生二次请求的发送,如果没有缓存,会发送一个安全且幂等的获取信息的GET请求
- GET 对于参数的数据类型,只接受ASCII字符
2.POST请求方式
一般用于数据的提交,包含数据的新增和修改,常用于表单的场合,只是可能修改变服务器上的资源的请求【可能:增加或者修改的结果有可能成功,也有可能失败,POST无法做出成功与否的保证,只能有后端的服务器进行数据 处理后才能被确认是否成功与否】
POST请求:
POST / HTTP/1.1
HTTP 协议中规定 POST 提交的数据必须在 body 部分中,但是协议中没有规定数据使用哪种编码
方式或者数据格式。实际开发中,完全可以自定义消息主体的格式,只要最后发送的 HTTP 请求
满足格式就可以。数据发送出去,还要服务端解析成功才有意义。一般服务端语言以及对应的web框架 Thymeleaf 、FreeMarker等,都内置了自动解析常见数据格式的功能。服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。故而POST 提交数据方案,包含了 Content-Type 和消息主体编码方式两部分
1.POST数据提交方式:application/x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded
浏览器原生支持的,是最常见的 POST 数据提交方式。浏览器的原生 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式为二进制数据使用多重编码提交数据。 body 当中的内容和 GET 请求是完全相同的。
2.POST数据提交方式:multipart/form-data
Content-Type: multipart/form-data
浏览器原生支持的,使用表单上传文件时,必须让 表单的enctype 等于 multipart/form-data的方式为二进制数据使用多重编码提交文件数据
<form action="/fileUpload" method="post" enctype="multipart/form-data">
<input type='text' name='textfield' id='textfield' class='txt' />
<input type="file" name="file" class="file" id="fileField" />
<input type="submit" name="submit" class="btn" value="上传" />
</form>
上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 表单也只支持这两种方式(通过 元素的 enctype 属性指定,默认为 application/xwww-form-urlencoded 。其实 enctype 还支持 text/plain,不过用得非常少)。
3.POST数据提交方式:text/plain
Content-Type: text/plain
将文件的content-type设置为纯文本的形式,如果是响应中设置,浏览器在获取到这种文件时并不会对其进行处理。使用频率非常低。
4.text/html和text/plain的区别
- text/html将文件的content-type设置为text/html的形式,浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理。
- text/plain将文件的content-type设置为纯文本的形式,浏览器在获取到这种文件时并不会对其进行处理。
5.注意
- POST 请求提交的数据必须在body中
- POST 请求没有在HTTP协议中被规定数据使用的编码格式或者数据格式,需要自行定义
- POST 请求提交的数据方案,包含Content-Type和消息主体编码方式两部分
- POST 请求对于使用thymeleaf、freemark等框架的web后台,服务端需要根据请求头中的Connect-Type来确认编码方式后然后才解析消息主体
- POST 请求不会被缓存
- POST 请求不会保留在浏览器历史记录中
- POST 请求不能被收藏为书签
- POST 请求对数据长度没有要求,HTTP 协议规范也没有进行大小限制,但是出于安全考虑,服务器软件在实现时会做一定限制
2.请求头
客户端(浏览器)向服务器发送请求的时候必须指明请求类型(一般是GET或者POST)。如有必要,客户程序还可以选择发送其他的请求头。大多数请求头并不是必需的,但Content-Length除外。对于POST请求来说Content-Length必须出现。
请求头部为请求报文添加了一些附加信息,由“名/值”对组成,每行一对,名和值之间使用冒号分隔。
1.典型的请求头
请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
请求头 | 含义 |
---|---|
Accept | 用来告知客户端可以处理的内容类型,这种内容类型用MIME类型【MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型】来表示。客户端可识别的响应内容类型列表,星号“ * ”用于按范围将类型分组,用“ / ”指示可接受全部类型,用“ type/* ”指示可接受 type 类型的所有子类型。 |
Accept-Language | 请求头允许客户端声明它可以理解的自然语言,以及优先选择的区域方言。 |
Accept-Encoding | 客户端可接受的编码压缩格式 |
Connection | 决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成,HTTP/1.1的请求默认使用一个持久连接(keep-alive)。close表明客户端或服务器想要关闭该网络连接,这是HTTP/1.0请求的默认值。 |
Cookie | 先前由服务器通过 Set-Cookie 首部投放并存储到客户端的 HTTP cookies。 |
Host | 指明了服务器的域名(对于虚拟主机来说),以及(可选的)服务器监听的TCP端口号。如果没有给定端口号,会自动使用被请求服务的默认端口(比如请求一个HTTP的URL会自动使用80端口)。HTTP/1.1 的所有请求报文中必须包含一个Host头字段。如果一个 HTTP/1.1 请求缺少 Host 头字段或者设置了超过一个的 Host 头字段,一个400(Bad Request)状态码会被返回。 |
Referer | 包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 Referer 首部识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。需要注意的是 referer 实际上是 “referrer” 误拼写。 |
User-Agent | 包含了一个特征字符串,用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。 |
2.典型请求头示例
Host: ss1.baidu.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Referer: https://www.baidu.com/
Cookie: BAIDUID=31215988502290362051F22CB67A33EA:FG=1; BIDUPSID=31215988502290362051F22CB67A33EA; PSTM=1557994094; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; BDRCVFR[Fc9oatPmwxn]=srT4swvGNE6uzdhUL68mv3; delPer=0; PSINO=1; H_PS_PSSID=1452_21092_29522_29519_28518_29099_28837_29221_28704; BDRCVFR[gltLrB7qNCt]=mk3SLVN4HKm
Connection: keep-alive
3.空行
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
4.请求包体
请求包体不在GET方法中使用,而在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求包体相关的最常使用的是包体类型Content-Type和包体长度Content-Length。
4.3.2.响应报文
HTTP 响应报文由状态行、响应头部、空行、响应包体组成:
1.状态行
状态行:协议版本、状态码、状态码描述
HTTP/1.1 200 OK
状态行由协议版本、数字形式的状态代码、及相应的状态描述,各元素之间以空格分隔。
状态码
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:
状态码类别 | 列表描述 |
---|---|
1xx | 信息,服务器收到请求,需要请求者继续执行操作 |
2xx | 成功,操作被成功接收并处理 |
3xx | 重定向,需要进一步的操作以完成请求 |
4xx | 客户端错误,请求包含语法错误或无法完成请求 |
5xx | 服务器错误,服务器在处理请求的过程中发生了错误 |
HTTP状态码:
状态码 | 状态描述 | 描述 |
---|---|---|
100 | Continue | 服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。 |
101 | Switching Protocols | 服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。例如从HTTP切换到WebSocket |
200 | OK | 请求成功(其后是对GET和POST请求的应答文档。一般用于GET与POST请求) |
201 | Created | 请求被创建完成,同时新的资源被创建。 |
202 | Accepted | 供处理的请求已被接受,但是处理未完成。 |
203 | Non-authoritative Information | 非授权信息。请求成功,文档已经正常地返回,但一些应答头可能不正确【返回的meta信息不在原始的服务器】,因为使用的是文档的拷贝【是一个副本】。 |
204 | No Content | 没有新文档,服务器成功处理,但未返回内容,浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,在未更新网页的情况下,可确保浏览器继续显示当前文档。 |
205 | Reset Content | 没有新文档。但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容。 |
206 | Partial Content | 客户发送了一个带有Range头【部分内容】的GET请求,服务器成功处理了部分GET请求 |
300 | Multiple Choices | 多重选择,链接列表【请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端】,用户可以选择某链接到达目的地,选择最多允许五个地址。 |
301 | Moved Permanently | 所请求的资源已经【永久】转移至新的URL,返回信息会包括新的URL,浏览器会自动定向到新URL。今后任何新的请求都应使用新的URI代替 ,【{ 请求重定向 },浏览器地址栏的URL会自动变成新的URL,301请求是可以缓存的, 即通过看status code,可以发现后面写着from cache】【如果不是GET 或者 HEAD 请求,浏览器禁止自动进行重定向,除非得到用户的确认,因为请求的条件可能因此发生变化。】尽管标准要求浏览器在收到该响应并进行重定向时不应该修改http method和body,但是有一些浏览器可能会有问题。所以最好是在应对 GET 或 HEAD 方法时使用301,其他情况使用 308 来替代301。 |
302 | Found | 所请求的页面已经【临时】转移至新的URL【{ 请求转发 },客户端应该使用原有的URL,只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。新的临时性的URI应当在响应的Location域中返回。除非这是一个HEAD请求,否则响应的实体中应当包含指向新的URI的超链接及简短说明】【如果不是GET 或者 HEAD 请求,浏览器禁止自动进行重定向,除非得到用户的确认,因为请求的条件可能因此发生变化。】即使规范要求浏览器在重定向时保证请求方法和请求主体不变,但并不是所有的用户代理都会遵循这一点,依然可以看到有缺陷的软件的存在。仅在响应 GET 或 HEAD 方法时采用 302 状态码,而在其他时候使用307 Temporary Redirect 来替代。 |
303 | See Other | 所请求的页面可在别的url下被找到 |
304 | Not Modified | 未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告知客户端,原来缓冲的文档还可以继续使用,不会返回任何资源。【传说中的条件GET常被返回304,未更新】 |
305 | Use Proxy | 客户请求的文档应该通过Location头所指明的代理服务器提取 |
306 | Unused | |
307 | Temporary Redirect | 临时重定向。与302类似。使用GET请求重定向,如果不是GET 或者 HEAD 请求,浏览器禁止自动进行重定向,除非得到用户的确认,因为请求的条件可能因此发生变化。 |
400 | Bad Request | 客户端请求的语法错误,服务器无法理解 |
401 | Unauthorized | 未授权,该请求需要用户的身份认证 |
402 | Payment Required | |
403 | Forbidden | 服务器已经理解请求,但是拒绝执行此请求。与401响应不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交 |
404 | Not Found | 服务器无法找到被请求的资源 |
405 | Method Not Allowed | 请求中指定的方法被禁止使用,请求行中指定的请求方法不能被用于请求相应的资源。响应必须返回一个Allow 头信息用以表示出当前资源能够接受的请求方法的列表。 |
406 | Not Acceptable | 请求的资源的内容特性无法满足请求头中的条件,无法完成请求,因而无法生成响应实体。 |
407 | Proxy Authentication Required | 请求要求代理的身份认证,与401响应类似,只不过客户端必须在代理服务器上进行身份验证。代理服务器必须返回一个 Proxy-Authenticate 用以进行身份询问 |
408 | Request Timeout | 请求超出了服务器的等待时间,超时 |
409 | Conflict | 服务器处理请求时和被请求的资源的当前状态之间存在冲突,冲突通常发生于对 PUT 请求的处理中,请求无法完成 |
410 | Gone | 客户端请求的资源已经不存在。被请求的资源在服务器上已经不再可用,而且没有任何已知的转发地址。这样的状况应当被认为是永久性的。410不同于404,如果资源以前存在现在被永久删除了可使用410代码,服务端可通过301代码指定资源的新位置 |
411 | Length Required | 服务器拒绝在没有定义 Content-Length 头的情况下接受请求。 |
412 | Precondition Failed | 客户端请求信息的先决条件错误,服务器在验证在请求的头字段中给出先决条件时,没能满足其中的一个或多个 |
413 | Request Entity Too Large | 服务器拒绝处理当前请求,因为该请求提交的实体数据大小超过了服务器允许或者能够处理的范围。服务器可以关闭连接以免客户端继续发送此请求。如果这个状况是临时的,服务器应当返回一个 Retry-After 的响应头,以告知客户端可以在多少时间以后重新尝试。 |
414 | Request-url Too Long | 请求的URI 长度超过了服务器能够解释的长度,因此服务器拒绝对该请求提供服务。 |
415 | Unsupported Media Type | 当前请求的方法和所请求的资源,请求中提交的实体并不是服务器中所支持的格式,请求被拒绝 |
416 | Requested Range Not Satisfiable | 请求中包含了 Range 请求头,并且 Range 中指定的任何数据范围都与当前资源的可用范围不重合,同时请求中又没有定义 If-Range 请求头 |
417 | Expectation Failed | 服务器无法满足Expect的请求头信息 |
500 | Internal Server Error | 服务器内部错误,无法完成请求 |
501 | Not Implemented | 服务器不支持请求的功能,无法完成请求 |
502 | Bad Gateway | 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应 |
503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 |
504 | Gateway Timeout | 充当网关或代理的服务器,未及时从远端服务器获取请求 |
505 | HTTP Version Not Supported | 服务器不支持请求的HTTP协议的版本,无法完成处理 |
2.响应头
1.典型的响应头
响应头 | 含义 |
---|---|
Location | Location 首部指定的是需要将页面重新定向至的地址。一般在响应码为3xx的响应中才会有意义。 |
Server | Server 首部包含了处理请求的源头服务器所用到的软件相关信息 |
Vary | Vary 是一个HTTP响应头部信息,它决定了对于未来的一个请求头,应该用一个缓存的回复(response)还是向源服务器请求一个新的回复。它被服务器用来表明在 content negotiation algorithm(内容协商算法)中选择一个资源代表的时候应该使用哪些头部信息(headers).在响应状态码为 304 Not Modified 的响应中,也要设置 Vary 首部,而且要与相应的 200 OK 响应设置得一模一样。 |
Connection | Connection 头(header) 决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成。 |
Content-Encoding | Content-Encoding 是一个实体消息首部,用于对特定媒体类型的数据进行压缩。当这个首部出现的时候,它的值表示消息主体进行了何种方式的内容编码转换。这个消息首部用来告知客户端应该怎样解码才能获取在 Content-Type 中标示的媒体类型内容。 |
Content-Type | Content-Type 实体头部用于指示资源的MIME类型 media type 。在响应中,Content-Type标头告诉客户端实际返回的内容的内容类型。浏览器会在某些情况下进行MIME【MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型】查找,并不一定遵循此标题的值; 为了防止这种行为,可以将标题 X-Content-Type-Options 设置为 nosniff。 |
Transfer-Encoding | Transfer-Encoding 消息首部指明了将 entity 安全传递给用户所采用的编码形式。Transfer-Encoding 是一个逐跳传输消息首部,即仅应用于两个节点之间的消息传递,而不是所请求的资源本身。一个多节点连接中的每一段都可以应用不同的Transfer-Encoding 值。如果你想要将压缩后的数据应用于整个连接,那么请使用端到端传输消息首部 Content-Encoding 。 |
Cache-Control | Cache-Control 通用消息头字段,被用于在http请求和响应中,通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中 |
Expires | Expires 响应头包含日期/时间, 即在此时候之后,响应过期。无效的日期,比如 0, 代表着过去的日期,即该资源已经过期。如果在Cache-Control响应头设置了 “max-age” 或者 “s-max-age” 指令,那么 Expires 头会被忽略。 |
2.典型的响应头示例
HTTP/1.1 200 OK
Bdpagetype: 1
Bdqid: 0x833b5ed4000b9d14
Cache-Control: private
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html
Cxy_all: baidu+5b77f61345b43740acd8fdb22bedafff
Date: Sun, 21 Jul 2019 08:21:48 GMT
Expires: Sun, 21 Jul 2019 08:21:47 GMT
Server: BWS/1.1
Set-Cookie: delPer=0; path=/; domain=.baidu.com
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=0; path=/
Set-Cookie: H_PS_PSSID=1436_21116_18559_29074_29523_29519_28518_29099_28833_29221_26350; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Vary: Accept-Encoding
X-Ua-Compatible: IE=Edge,chrome=1
Transfer-Encoding: chunked
3.空行
最后一个响应头部之后是一个空行,发送回车符和换行符,通知服务器以下不再有响应头部。
4.响应正文/响应包体
服务器返回给客户端的文本信息
4.4.条件GET
HTTP 条件 GET 是 HTTP 协议为了减少不必要的带宽浪费,提出的一种方案
4.4.1.HTTP 条件 GET 使用的时机
客户端之前已经访问过某网站,并打算再次访问该网站。
4.4.2.HTTP 条件 GET 使用的方法
客户端向服务器发送一个包询问是否在上一次访问网站的时间后是否更改了页面,如果服务器没有更新,显然不需要把整个网页传给客户端,客户端只要使用本地缓存即可,如果服务器对照客户端给出的时间已经更新了客户端请求的网页,则发送这个更新了的网页给用户。
4.4.3.HTTP 条件 GET 使用示例
- 客户端二次发送请求:
GET /5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/jquery/jquery-1.10.2.min_65682a2.js HTTP/1.1
Host: ss1.bdstatic.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br
Referer: https://www.baidu.com/
Connection: keep-alive
If-Modified-Since: Mon, 07 Nov 2016 07:51:11 GMT
If-None-Match: "16e36-540b1498e39c0"
Cache-Control: max-age=0, no-cache
Pragma: no-cache
初次请求时,服务器端返回请求数据,之后的请求,服务器根据请求中的 If-Modified-Since
字段判断响应文件没有更新,如果没有更新,服务器返回一个 304 Not Modified 响应,告诉浏
览器请求的资源在浏览器上没有更新,可以使用已缓存的上次获取的文件。
- 服务端响应请求:
HTTP/2.0 304 Not Modified
server: JSP3/2.0.14
date: Sun, 21 Jul 2019 17:10:47 GMT
content-type: application/javascript
content-length: 0
content-encoding: gzip
etag: "16e36-540b1498e39c0"
last-modified: Mon, 07 Nov 2016 07:51:11 GMT
expires: Wed, 31 Jan 2029 06:20:47 GMT
age: 14554200
accept-ranges: bytes
cache-control: max-age=315360000
vary: Accept-Encoding,User-Agent
ohc-cache-hit: bj2cm54 [4]
ohc-response-time: 1 0 0 0 0 0
X-Firefox-Spdy: h2
如果服务器端资源已经更新的话,就返回正常的响应
4.5.持久连接/连接重用
4.5.1.持久连接简介
- HTTP 协议采用【请求-应答】模式,当使用非 Keep-Alive的普通模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP 协议为无连接的协议);
- 当使用 Keep-Alive 模式(又称持久连接、连接重用)时,Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。
- 在 HTTP 1.0 版本中,并没有官方的标准来规定 Keep-Alive 如何工作,实际上是被附加到 HTTP 1.0协议上,如果客户端浏览器支持 Keep-Alive ,在HTTP请求头中添加一个字段 Connection: Keep-Alive,服务器收到有 Connection: Keep-Alive 的请求时,会在响应头中添加同样的字段来使用 Keep-Alive 。这样一来,客户端和服务器之间的HTTP连接就会被保持,不会断开(超过 Keep-Alive 规定的时间,意外断电等情况除外),当客户端发送另外一个请求时,就使用这条已经建立的连接。
- 在 HTTP 1.1 版本中,默认所有连接都被保持,如果加入Connection: close才关闭。目前大部分浏览器都使用 HTTP 1.1 协议,也就是说默认都会发起 Keep-Alive 的连接请求,是否能完成一个完整的 Keep-Alive 连接就看服务器设置情况。
由于 HTTP 1.0 没有官方的 Keep-Alive 规范,且已经基本被淘汰,所以对于**Connection:Keep-Alive **是按HTTP 1.1 标准展开的。
4.5.2.持久连接注意事项
- 1. HTTP Keep-Alive 保持当前的TCP连接,避免了重新建立连接。
- 2. HTTP 长连接不能一直保持,具有一定的生命周期,例如 Keep-Alive: timeout=5, max=100 ,表示这个TCP通道可以保持5秒,max=100,表示这个长连接最多接收100次请求就断开。
- 3. HTTP 是无状态协议,意味着每个请求都是独立的,Keep-Alive 没能改变这个结果。在HTTP1.1版本中Keep-Alive也不能保证客户端和服务器之间的连接一定是活跃的。唯一能保证的就是当连接被关闭时能得到一个通知,所以不可以让程序依赖于 Keep-Alive 的保持连接特性,否则会有意想不到的后果。
4.5.3.使用长连接之后,客户端、服务端判定传输的结束
- 1.判断传输数据是否达到了Content-Length 指示的大小;
- 2.动态生成的文件没有 Content-Length ,它是分块传输(chunked),这时候就要根据 chunked 编码来判断,chunked 编码的数据在最后有一个空 chunked 块,表明传输数据结束。
4.5.4.HTTP的keep-alive与TCP的keep-alive的关系
- 1.两种不同的机制
- 2.HTTP在头部的Connection中声明keep-alive可以告知对方要长连接不立即断开
- 3.TCP的keep-alive则是一种检查对方是否仍旧和自己保持着连接的机制以避免自作多情半开放的连接。假如发出一个探测段,成功收到响应,这证明连接正常保持;假如发出一个探测段一段时间后,一个响应都没收到,对方可能已挂断、机器异常或网络异常;假如对方收到探测段但重置,说明原来的连接已经因为某些原因挂断,目前是因为未进行三次握手新建立连接而被挂断。
4.6.Transfer-Encoding
4.6.1.Transfer-Encoding简介
- Transfer-Encoding 是一个用来标示 HTTP 报文传输格式的头部值。尽管这个取值理论上可以有很多,但是当前的 HTTP 规范里实际上只定义了一种传输取值——chunked。
- 如果一个HTTP消息(请求消息或应答消息)的Transfer-Encoding消息头的值为chunked,消息体由数量未定的块组成,并以最后一个大小为0的块为结束。
每一个非空的块都以该块包含数据的字节数(字节数以十六进制表示)开始,跟随一个CRLF (回车及换行),然后是数据本身,最后块CRLF结束。在一些实现中,块大小和CRLF之间填充有空白格。- 最后一块是单行,由块大小(0),一些可选的填充白空格,以及CRLF。最后一块不再包含任何数据,但是可以发送可选的尾部,包括消息头字段。消息最后以CRLF【回车换行】结尾。
4.6.2.Transfer-Encoding注意事项
- chunked 和 multipart 两个名词在意义上有类似的地方,不过在 HTTP 协议当中这两个概念则不是一个类别的。
- multipart 是一种 Content-Type,标识 HTTP 报文内容的类型,chunked 是一种传输格式,标识报头将以何种方式进行传输。
- chunked 传输不能事先知道内容的长度,只能靠最后的空 chunk 块来判断,对于chunked 方式进行下载的下载请求来说,是没有办法实现进度的。在浏览器和下载工具中,偶尔会看到有些文件是看不到下载进度的,即采用 chunked 方式进行下载。
- chunked 的优势在于,服务器端可以边生成内容边发送,无需事先生成全部的内容。HTTP/2不支持 Transfer-Encoding: chunked,因为 HTTP/2 有自己的 streaming 传输方式。
4.7.HTTP Pipelining(HTTP 管线化)
HTTP的连接管理可以查到管线化HTTP Pipelining知识
4.7.1.HTTP 管线化简介
- 默认情况下 HTTP 协议中每个传输层连接只能承载一个HTTP请求和响应,浏览器会在收到上一个请求的响应之后,再发送下一个请求。在未使用持久连接的情况下,单个连接上消息的传递类似于:
请求A——>响应A——请求B——>响应B——>请求C——>响应C
- HTTP Pipelining(管线化)是将多个 HTTP 请求批量提交的技术,在传送过程中不需等待服务端的回应。使用 HTTP Pipelining 技术之后,单个连接上的消息传递类似于:
请求A——请求B——>请求C——>响应A——>响应B——>响应C
4.7.1.HTTP 管线化注意事项
- 1.管线化机制通过持久连接(persistent connection)完成,仅HTTP/1.1 支持此技术(HTTP/1.0不支持)
- 2.只有 GET 和 HEAD 请求可以进行管线化,而 POST 则有所限制
- 3.初次创建连接时不应启动管线机制,因为对端(服务器)不一定支持 HTTP/1.1 版本的协议
- 4.管线化不会影响响应到来的顺序,响应返回的顺序会根据请求的顺序进行,响应返回的顺序并未发生改变
- 5.HTTP /1.1 要求服务器端支持管线化,但并不要求服务器端也对响应进行管线化处理,只是要求对于管线化的请求不失败即可
- 6.由于服务器端开启管线化很可能并不会带来大幅度的性能提升,而且服务器端和代理程序对管线化的支持并不好,因此现代浏览器如 Chrome 和 Firefox 默认并未开启管线化持。
4.8.会话跟踪
4.8.1.什么是会话
客户端打开与服务器的连接发出请求到服务器响应客户端请求的全过程称之为会话。
4.8.2.什么是会话跟踪
会话跟踪指的是对同一个用户对服务器的连续的请求和接受响应的监视。
4.8.3.为什么需要会话跟踪
- 浏览器与服务器之间的通信是通过HTTP协议进行通信的
- HTTP协议是无状态的协议
- 无状态意味着不能保存客户的信息,即一次响应完成之后连接就断开了,下一次请求需要重新连接,就需要判断是否是同一个用户,所以才有会话跟踪技术来实现这种要求。
4.8.4.会话跟踪常用的方法
4.8.4.1. URL重写
URL(统一资源定位符)是Web上特定页面的地址,URL重写的技术就是在URL结尾添加一个附
加数据以标识该会话,把会话ID通过URL的信息传递过去,以便在服务器端进行识别不同的用
户。
4.8.4.2.表单隐藏域
将会话ID添加到HTML表单元素的隐藏域中提交到服务器,此表单元素并不在客户端显示
4.8.4.3.Cookie
Cookie是Web服务器发送给客户端并由客户端存储的简短信息,客户端请求时可以读取该信息发送到服务器端,进而进行用户的识别。对于客户端的每次请求,服务器都会将Cookie发送到客户端,在客户端可以进行保存,以便下次使用。
客户端保存Cookie对象的方式:
- 1.保存在客户端内存中,称为临时Cookie,浏览器关闭后这个Cookie对象将消失。
- 2.保存在客户机的磁盘上,称为永久Cookie,以后客户端只要访问该网站,就会将这个在有效期内的Cookie再次发送到服务器上,从而实现了对客户的跟踪。
注意:
Cookie是可以被用户的客户端(浏览器)设置禁用或者清空Cookie,所以一般不在实际开发中使用Cookie作为会话跟踪技术的首选方式。
4.8.4.4. Session
每一个用户都有一个不同的session,各个用户之间是不能共享的,是每个用户所独享的,在session中可以存放信息。在服务器端会创建一个session对象,产生一个sessionID来标识这个session对象,然后将这个sessionID放入到Cookie中发送到客户端,下一次访问时,sessionID会发送到服务器,在服务器端进行识别不同的用户。
注意:
Session的实现依赖于Cookie,如果Cookie被禁用或者被清空,那么session也将失效。
4.9.跨站请求伪造/攻击CSRF(Cross-Site Request Forgery)
4.9.1.跨站请求伪造/攻击CSRF(Cross-Site Request Forgery)简介
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF,是一种对网站的恶意利用。尽管像跨站脚本(XSS),但与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装成受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
4.9.2.防范CSRF 攻击
1.关键操作只接受POST请求
2.验证码
CSRF攻击的过程,往往是在用户不知情的情况下构造网络请求。所以如果使用验证码,那么每次操作都需要用户进行互动,从而简单有效的防御了CSRF攻击。但是如果在一个网站作出任何举动都要输入验证码会严重影响用户体验,所以验证码一般只出现在特殊操作里面,或者在注册时候使用。
3.检测 Referer
常见的互联网页面与页面之间是存在联系的,比如你在 www.baidu.com 应该是找不到通往 www.google.com 的链接的,再比如在论坛留言,那么不管留言后重定向到哪里去了,之前的那个网址一定会包含留言的输入框,这个之前的网址就会保留在新页面头文件的Referer 中通过检查 Referer 的值,我们就可以判断这个请求是合法的还是非法的,但是问题出在服务跨站攻击器不是任何时候都能接受到 Referer 的值,所以 Referer Check 一般用于监控 CSRF攻击的发生,而不用来抵御攻击。
4.Token
1.目前主流的做法是使用 Token 抵御 CSRF 攻击。
Token 能够有效CSRF攻击要成功的条件在于攻击者能够预测所有的参数从而构造出合法的请求,根据不可预测性原则,可以对参数进行加密从而防止CSRF攻击。
2.更通用的做法是保持原有参数不变,另外添加一个参数Token,其值是随机的。攻击者因为不知道Token而无法构造出合法的请求进行攻击。
Token 使用原则
- Token 要足够随机:随机的才能实现不可预测
- Token 是一次性的:即每次请求成功后要更新Token,可以增加攻击难度,增加预测难度
- Token 保密性:敏感操作使用 post,防止Token 出现在URL中
注意事项
过滤用户输入的内容不能阻挡 CSRF,需要是过滤请求的来源。
4.10.XSS(Cross Site Scripting,跨站脚本攻击)
4.10.1.XSS简介
XSS(Cross Site Scripting) 全称“跨站脚本”,是注入攻击的一种。其特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文本,此时服务器端如果没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个页面的时候就会运行这些脚本。
4.10.2.XSS与CSRF的关系
XSS 是实现 CSRF 的诸多途径中的一条,但绝对不是唯一的一条。一般习惯上把通过 XSS 来实现的 CSRF 称为 XSRF。
4.10.3.防御 XSS 攻击
理论上,所有可输入的地方没有对输入数据进行处理的话,都会存在XSS漏洞,漏洞的危害取决
于攻击代码的威力,攻击代码也不局限于script。防御 XSS 攻击最简单直接的方法,就是过滤
用户的输入。
- 如果不需要用户输入 HTML,可以直接对用户的输入进行 HTML escape 。
<script>window.location.href=”http://www.baidu.com”;</script>
经过 escape 之后就成了:
<script>window.location.href="http://www.baidu.com"</script>
会像普通文本一样显示出来,变得无毒无害,不能执行了。
- 当需要用户输入 HTML 的时候,需要对用户输入的内容做更加小心细致的处理。仅仅粗暴地去掉JavaScript标签是没有用的,任何一个合法 HTML 标签都可以添加 onclick 一类的事件属性来执行 JavaScript。更好的方法可能是,将用户的输入使用 HTML 解析库进行解析,获取其中的数据。然后根据用户原有的标签属性,重新构建 HTML 元素树。构建的过程中,所有的标签、属性都只从白名单中拿取。
4.11.浏览器输入一个URL的过程
- 1.重定向判断:判断是否需要重定向,重定向到哪里
例如:从http://www.baidu.com会有一个307的重定向到https://www.baidu.com - 2.缓存判断:如果请求的资源没有被缓存,就去服务器获取资源。
- 3.DNS解析:浏览器首先去找本地的hosts文件,检查在该文件中是否有相应的域名、IP对应关系,如果有,则向其IP地址发送请求,如果没有就会将DoMain(域)发送给 DNS(域名服务器)进行解析,将域名解析成对应的服务器IP地址,发回给浏览器,然后根据域名到DNS中找到IP
- 4.建立TCP连接:根据IP建立TCP连接(三次握手)
- 5.HTTP请求并发送数据:连接建立成功发起HTTP请求,发送数据
- 6.响应:服务器响应HTTP请求
- 7.DOM解析及静态资源获取:浏览器解析HTML代码并请求HTTP中的静态资源(js,css)
- 8.断开TCP连接:关闭TCP连接(四次挥手)
- 9.页面渲染:浏览器渲染页面
5.HTTPS
5.1.HTTPS简介
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer 或 Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。这个系统的最初研发由网景公司(Netscape)进行,并内置于其浏览器Netscape Navigator中,提供了身份验证与加密通讯方法。
5.2.HTTPS和HTTP的区别
- 1.https协议需要到CA申请证书,一般免费证书很少,需要交费。
- 2.http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
- 3.http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- 4.http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
6.HTTP2
- 所有数据都以二进制进行传输【帧】
- 同一个连接里面发送多个请求不再需要按照顺序执行–由HTTP1.1的pipeline的串行升级为并行,从而实现效率提升
- 头信息压缩以及推送等提高效率的功能
头信息压缩的概念
在HTTP1.1中每一次发送请求和响应中,很多的HTTP的header头都是必须要完整的发送与接收,但是头部的信息中有很多的字段,比如content-Type和Content-Encoding等是以字符串的形式保存,导致header头部信息对带宽的占用比较大,在HTTP2中对头部header信息进行压缩,减少带宽的使用.
推送的概念
传统的HTTP是客户端是主动方,服务器是被动方,只能由客户端进行请求的发起,而服务器只能取响应请求,在HTTP2中,服务端可以主动发起数据传输,而不用等客户端的请求的发起。解决了,HTML和css/JS 的传输,在传统过程中,是一个串行过程,需要将HTML文件响应个客户端请求后,先进行解析HTML的DOM文件,然后通过HTML中的引用来请求响应的js和css文件,在HTTP2中,利用推送,可以在响应HTML的同时并行的将需要的css和js文件推送回去,而不用等HTML解析完HTML的dom结构后再来请求css和js并响应,实现了并行的过程。
6.1.HTTP现状
互联网上几乎所有内容都采用HTTP 1.1作为通信协议。在此协议上投入了大量精力,基于它的基础架构也因此日臻完善。正因如此,在HTTP协议之上构建新的方案会比从底层建立新的协议容易得多。
6.2.HTTP1.1缺陷
1.HTTP 1.1过于庞大
HTTP刚诞生的时候只被当作是一个相对简单直观的协议,但时间证明这种初始设计并不如意。定义HTTP 1.0规范的RFC 1945共有60页,发布于1996年。仅仅3年之后,定义HTTP 1.1规范的RFC 2616却一下增长到了176页。然而,在IETF在进行该规范更新工作时,它被拆分成了总页数更多的六个文档(这就是RFC 7230及其文件族的诞生)。HTTP 1.1包含了太多细节和可选的部分,这让它变得过于庞大。
2.过多的可选项
HTTP 1.1不仅包含了非常多的细枝末节,还为将来的扩展预留的很多选项。这种事无巨细的风格导致在现在的软件生态中,几乎没有任何实现真正实现了协议中提及的所有细节,甚至要弄清楚“所有细节”到底包括哪些细节都非常困难。正因为如此,很多最初不常用的功能在后来的实现中很少会被支持,而有些最初实现了的功能,却又很少被使用。随着时间推移,当初看似被边缘化的功能逐渐被用上,客户端和服务器的互用性(interoperability)问题就被暴露了出来。例如HTTP的管线化(HTTP Pipelining)机制。
3.未能充分利用TCP
HTTP 1.1很难充分利用TCP协议所能提供的所有性能。HTTP客户端和浏览器必须要另辟蹊径的去找到新的解决方案来降低页面载入时间。
与此同时,尝试去用新的协议来替代TCP,但结果证明这也非常困难。无奈之下,只能尝试同时改进TCP协议本身和基于TCP的上层协议。
简言之,通过更好的利用TCP来减少传输过程中的暂停,并充分挖掘利用那些本可以用于发送/接受更多数据的时间。
4.传输大小和资源数量
在当前的互联网时代,加载网站首页需要下载的数据量在逐渐增加,显示每个页面所需下载的平均资源数也在逐渐增长,请求的资源数量也在增长态势愈发严重。
6.3.HTTP2协议
1. 二进制
http2是一个二进制协议。
二进制的http2可以使成帧更便捷。在HTTP1.1和其他基于文本的协议中,识别帧的起始和结束相当复杂。而在移除掉可选的空白符和其他冗余后,实现这些会变得更容易。
另一方面,从帧结构中分离出协议本身的部分也变得更容易。而在HTTP1中,各个部分相互交织,一团乱麻。
协议的压缩特点和其经常运行在TLS之上的事实让纯文本的属性值变得毫无作用,毕竟也无法从数据流上看到文本。
2. 二进制格式
http2发送二进制帧。
帧的类型有很多种,但都有如下的公共字段:
Type, Length, Flags, Steam Identifier和frame payload
BREACH和CRIME攻击的隐患。通过向流中注入一些已知的文本来观察输出的变化,攻击者可以推出原始发送的数据。
为协议的动态内容进行压缩并使其免于被攻击,需要仔细且全面的考虑。而这正是HTTPbis小组尝试去做的。
HPACK,HTTP/2头部压缩,顾名思义它是一个专为http2头部设计的压缩格式。确切的讲,它甚至被制定写入在另外一个单独的草案里。新的格式同时引入了一些其他对策让破解压缩变得困难,例如采用帧的可选填充和用一个bit作为标记,来让中间人不压缩指定的头部。
用Roberto Peon(HPACK的设计者之一)的话说,“HPACK旨在提供一个一致性的实现使信息量的损失尽可能少,使编解码快速而方便,使接收方能控制压缩文本的大小,允许代理重新建立索引(如,通过代理在前后端共享状态),以及对哈夫曼编码串的更快速比较”。
3. 重置
HTTP2通过发送RST_STREAM帧来实现消息中断,而不用断开TCP连接
HTTP 1.1的有一个缺点是:当一个含有确切值的Content-Length的HTTP消息被送出之后,就很难中断。当然,可以断开整个TCP链接(但也不总是可以这样),这样导致的代价就是需要重新通过三次握手建立一个新的TCP连接。
一个更好的方案是只终止当前传输的消息并重新发送一个新的。在http2里面,可以通过发送RST_STREAM帧来实现这种需求,从而避免浪费带宽和中断已有的连接。
4. 服务器推送
这个功能通常被称作“缓存推送”。主要的思想是:当一个客户端请求资源X,而服务器知道它很可能也需要资源Z的情况下,服务器可以在客户端发送请求前,主动将资源Z推送给客户端。这个功能帮助客户端将Z放进缓存以备将来之需。
服务器推送需要客户端显式的允许服务器提供该功能。但即使如此,客户端依然能自主选择是否需要中断该推送的流。如果不需要的话,客户端可以通过发送一个RST_STREAM帧来中止。
5. 流量控制
http2上每个流都拥有自己的公示的流量窗口,它可以限制另一端发送数据。这与SSH的工作原理非常相似。
对于每个流来说,两端都必须告诉对方自己还有更多的空间来接受新的数据,而在该窗口被扩大前,另一端只被允许发送这么多数据。只有数据帧受流量控制。
7.WebSocket
8.RESTful
9.RPC(Remote Procedure Call远程过程调用)协议
9.1.RPC(Remote Procedure Call远程过程调用)简介
远程过程调用(Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。
该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。
远程过程调用是一个**分布式计算的客户端-服务器(Client/Server)**的例子,它简单而又广受欢迎。
远程过程调用总是由客户端对服务器发出一个执行若干过程请求,并用客户端提供的参数。执行结果将返回给客户端。
由于存在各式各样的变体和细节差异,对应地派生了各式远程过程调用协议,而且它们并不互相兼容。为了允许不同的客户端均能访问服务器,许多标准化的 RPC 系统应运而生了。其中大部分采用接口描述语言(Interface Description Language,IDL),方便跨平台的远程过程调用。
RPC 本身是 client-server模型,也是一种request-response 协议【请求-应答】。
9.2.服务的调用过程
- 1.client调用client stub,这是一次本地过程调用
- 2.client stub将参数打包成一个消息,然后发送这个消息。打包过程也叫做 marshalling
- 3.client所在的系统将消息发送给server
- 4.server的的系统将收到的包传给server stub
- 5.server stub解包得到参数。 解包也被称作 unmarshalling
- 6.最后server stub调用服务过程. 返回结果按照相反的步骤传给client
注意:
- 客户端(Client): 服务的调用方
- 服务端(Server):真正的服务提供者
- 客户端存根(client stub):存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方
- 服务端存根(server stub):接收客户端发送过来的消息,将消息解包,并调用本地的方法
9.3.RPC框架
RPC只是描绘了 Client 与 Server 之间的点对点调用流程,包括 stub(存根)、通信、RPC 消息解析等部分,在实际应用中,还需要考虑服务的高可用、负载均衡等问题,所以产品级的 RPC 框架除了点对点的 RPC 协议的具体实现外,还应包括服务的发现与注销、提供服务的多台Server 的负载均衡、服务的高可用等更多的功能。
目前的 RPC 框架大致有两种不同的侧重方向,一种偏重于服务治理,另一种偏重于跨语言调用。
RPC侧重方向 | 常见RPC | 特点 | 缺点 |
---|---|---|---|
服务治理型RPC | Alibab Dubbo、Motan 等 | 功能丰富,提供高性能的远程调用以及服务发现和治理功能,适用于大型服务的微服务化拆分以及管理,对于特定语言(Java)的项目可以十分友好的透明化接入。 | 语言耦合度较高,跨语言支持难度较大。 |
跨语言调用型RCP | Thrift、gRPC、rpcx等 | 关注于服务的跨语言调用,能够支持大部分的语言进行语言无关的调用,非常适合于为不同语言提供通用远程服务的场景 。 | 没有服务发现相关机制,实际使用时一般需要代理层进行请求转发和负载均衡策略控制。 |
9.3.1.Dubbo–电商
Dubbo 是阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。Dubbo由于跟淘宝另一个类似的框架HSF(非开源)有竞争关系,导致dubbo团队已经解散;在电商圈如当当 (dubbox)、京东、国美维护了自己的分支或者在dubbo的基础开发,但是官方的实现缺乏维护,其它电商虽然维护了自己的版本,但是还是不能做大的架构的改动和提升,相关的依赖类比如Spring,Netty还是很老的版本(Spring 3.2.16.RELEASE, netty3.2.5.Final),而且Dubbo的代码结构过于复杂。
9.3.2.Motan–互联网
Motan是新浪微博开源的一个Java 框架。它诞生的比较晚,起于2013年,2016年5月开源。Motan 在微博平台中已经广泛应用,每天为数百个服务完成近千亿次的调用。Motan的架构相对简单,功能也能满足微博内部架构的要求,虽然Motan的架构的目的主要不是跨语言,但是目前也在开发支持php client和C server特性。
9.3.3.Thrift
Thrift是Apache的一个跨语言的高性能的服务框架,也得到了广泛的应用。它的功能类似 gRPC, 支持跨语言,不支持服务治理。
9.3.4.gRPC
gRPC是Google开发的高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。目标是跨语言开发,支持多种语言, 服务治理方面需要自行实现,所以实现一个综合的产品级的分布式RPC平台还需要扩展开发,Google内部使用的也不是gRPC,而是Stubby。
9.3.5.RPCX
rpcx 是一个分布式的Go语言的 RPC 框架,支持Zookepper、etcd、consul多种服务发现方式,多种服务路由方式, 是目前性能最好的 RPC 框架之一。
9.4.RPC 和 RESTful
RPC 的消息传输可以通过 TCP、UDP 或者 HTTP等,所以称之为 RPC over TCP、 RPC over HTTP。RPC 通过 HTTP 传输消息的时候和 RESTful的架构是类似的,但也有不同。
9.4.1.RPC over HTTP 和 RESTful
RPC over HTTP | RESTful |
---|---|
RPC 的客户端和服务器端是紧耦合的,客户端需要知道调用的过程的名字,过程的参数以及它们的类型、顺序等。一旦服务器更改了过程的实现,客户端的实现很容易出问题。 | RESTful基于HTTP的语义操作资源,参数的顺序一般没有关系,也很容易的通过代理转换链接和资源位置,故而RESTful 更灵活。 |
RPC 操作的是方法和过程,要操作的是方法对象。 | RESTful 操作的是资源(resource),而不是方法。 |
RPC提供方法调用,如果实现一个特定目的的操作,比如为名字姓张的学生的数学成绩都加上10这样的操作,可以实现一个 Student.Increment(Name, Score) 的方法供客户端调用。 | RESTful执行的是对资源的操作,增加、查找、修改和删除等,主要是CURD,如果实现一个特定目的的操作,比如为名字姓张的学生的数学成绩都加上10这样的操作,RESTful的API设计起来就不是那么直观或者有意义。 |
9.4.2.RPC over TCP 和 RESTful
RPC over TCP | RESTful |
---|---|
通过长连接减少建立简介产生的资源消耗,高并发场合愈发重要。 | 通过在请求头中设置Connection: keep-alive实现长连接****,request-response模型阻塞严重,必须等前一个请求发送并完成响应后,才能发送后续请求,即使在HTTP1.1中使用了Pipeline管线化技术,依然是一个串行化的方案,且服务器端开启Pipeline管线化很可能并不会带来大幅度的性能提升,而且服务器端和代理程序对管线化的支持并不好,非标配,除非升级到HTTP2, RPC的实现没有这个限制。 |
采用TCP通讯协议,是传输层的通信协议,效率和性能高于应用层协议,普遍用于微服务架构的服务之间的通讯 | RESTful基于HTTP,是应用层协议,基于传输层协议之上,效率和性能比传输层的协议要低 |