前言
最近决定重新梳理自己的知识体系,查缺补漏。读了《图解http》这本书,觉得这边书比起枯燥的网络数据,对于前端同学来说通俗易懂、深入浅出,很适合前端同学读下去,记录一下读完后总结的知识和体会吧
一 TCP/IP协议基础
1、TCP/IP协议族概念
计算机网络之间的通信,必须基于一定的规则和语言,这些规则就是协议。协议不止一种,把鱼互联网相关联的协议的集合称为TCP/IP协议族(摘自:《图解HTTP》)
2.TCP/IP的分层
将网络分层设计的作用:分层之后,某一层变动或者修改的时候就不需要将整体替换掉,只需要修改对应的层级就行,各层的接口部分部署好后,每一层各司其职互不干扰。
下图是OSI七层模型和TCP/IP模型之间的一个对比和概览(摘自:https://juejin.cn/post/6844903510509633550,感谢该作者)
TCP/IP模型分为四层:从上到下划分为应用层、传输层、网络层、链路层
- 应用层:向用户提供应用服务时候的一系列通信活动,常见应用服务协议:FTP,DNS,HTTP等
- 传输层:用于两个网络设备之间传输具体的数据包,主要两种协议:TCP和UDP协议
- 网络层:主要作用是为两台通信的设备,在庞大的互联网上选择一条传输线路
- 链路层:用来连接网络的硬件部分,设备驱动,网卡,光纤等
3.TCP/IP通信传输流
从应用层到接收方的通信过程,我们以一个完整的流程来说明。
- 发送数据的一方从应用层开始往下走,我们常常以域名去访问服务器,也就是通信对方,而不是直接通过IP地址来访问,因此应用层DNS服务发挥作用了,她通过域名查找出ip地址,确定通信对方的ip地址(摘自:《图解HTTP》)
- 在传输层,TCP为了更容易将数据传递出去会进行数据分割成报文段进行传输,TCP协议将数据包丢出去后还会向对方确定是否成功送达,就采用三次握手策略,后面将详细说明
- 数据包有了,但是在错综复杂的网络上这些数据包走哪一条路线进行传输呢,于是该层中最突出的协议Internet协议(IP)发挥作用了,因此该层也称为IP层。ip协议根据传输对方的ip地址,首先查询自己的路由表。 在命令行输入route print,可查看路由表
看在自己的路由表中能否找到去往目标网络的路由条目,没有查找到与对方ip相匹配的具体路由,就会走默认路由(例如上图192.168.95.254),于是通过默认网关的ip地址经过ARP协议的解析,解析出下一站的默认网关的MAC地址,MAC地址是指网卡所属的物理标识,就这样层层查找下一站的转发路线,最终传递给通信目标
- 有了物理地址后就可以就可以转发给链路层,通信请求准备齐全了 与发送端相反的是,接受端是从链路层到应用层进行处理的,下图说明一个完整的流程(摘自:《图解HTTP》)
4.三次握手
TCP是可靠性地传输协议,所以在传输数据前进行三次握手确保两端做好准备,
具体过程:
-
客户端发送SYN报文给服务器端,序号seq=a,客户端进入SYN_SEND状态,等待服务器确认。
-
服务器端收到SYN报文,回应一个SYN+ACK报文,确认序号ack = a+1, 发送序号为seq = b,进入SYN_RECV状态。 双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。
-
客户端收到服务器端的SYN报文,回应一个ACK报文确认发,确认号ack = b+1 发送序号seq = a+1,进入Established状态。 三次握手完成。 整个过程通俗的可以理解为:
-
客户端询问服务端:你在吗?
-
服务端:我在
-
客户端:我要开始发消息了
为什么要进行三次握手连接:
为了防止无效的连接请求报文到达服务器而引起错误。三次握手的最主要目的是保证连接是双工的,可靠更多的是通过重传机制来保证的。
TCP发起建立连接的一方不会一直等待对方的回复,如果超时,他再次发起这个请求,上一个作废。比如因为某些原因下,之前客户端发送的连接请求到达了服务端,其实这个请求已经作超时作废了,但是服务端收到这个建立连接的请求后就会作出应答,如果是两次握手的话,服务器做出应答就已经建立连接了,会一直等待客户端进行通信,但其实这个请求已经作废,服务端不是想建立连接的状态,因此并不会理会服务端的,所以服务器的资源就白白占用了
5.四次挥手
断开一个TCP连接时,需要客户端和服务端发送四次数据包以确认断开连接
连接过程:
- 第一次挥手:客户端发送一个FIN报文,序列号seq = a,用来关闭客户端到服务端的连接,客户端进入FIN_WAIT_1状态。
- 第二次挥手:服务端收到FIN后,发送一个ACK给客户端,确认序号为收到序号seq= a+1(与SYN相同,一个FIN占用一个序号),服务端进入CLOSE_WAIT状态。
- 第三次挥手:服务端发送一个FIN,序列号seq = b,ack = a+ 1用来关闭服务端到客户端的数据传送,服务端进入LAST_ACK状态。
- 第四次挥手:客户端收到FIN后,接着发送一个ACK给服务端,序列号seq = b+1,Server进入CLOSED状态,客户端进入TIME_WAIT状态,Server进入CLOSED状态,但是客户端这边需要等待2MSL后依然没有收到回复,则证明Server端已正常关闭,客户端就可以关闭连接了。
通俗的说法
- 客户端: 我要关闭连接了
- 服务端: 知道了,还有工作没处理完,稍等
- 服务端:好了,我这边可以关闭了
- 客户端: 好的,确认关闭。
为什么要四次挥手
为了保证数据的传输的完整性,客户端发起关闭的请求的时候,服务端的ACK和FIN是分开发的,为了确保数据传输都完成了,才能告诉客户端同意关闭连接
为什么客户端需要2MSL等待状态
- 确保第四次握手时客户端发送的ACK可以到达服务端,如果2MSL时间内没有收到,则客户端会进行重发
- 确保网络上存在的数据包因为过期而消失(每个具体TCP实现必须选择一个报文段最大生存时间MSL。它是任何报文段被丢弃在网络内的最长时间。 2MSL足够使所有报文过期了)
二 HTTP协议认识
- HTTP协议是应用层协议,用于客户端和服务端进行通信
- 使用HTTP通信时候,在一条线路上必然有一端是客户端。另一端是服务端。 通过客户端发送请求,服务端响应的方式实现通信
1.WEB服务器
HTTP通信时候离不开服务器,因此先简单介绍一下web服务器。
(1)用虚拟主机可以实现一个web服务器上部署多个域名的网站;
- 使用虚拟主机可以让一个服务器下寄存多个主机名和域名的网站,域名可以通过DNS服务映射到服务器的IP地址。所以在HTTP请求时候,在请求头中的HOST中必须完整指定主机名或者域名的url
(2)配合服务器工作的数据转发程序
- 代理:一种有转发功能的应用程序,充当了客户端和服务器之间中间人的角色,有正向代理(代理客户端)和反向代理(代理服务端),常用的nginx就是反向代理
- 网关:通过中间的网关进行处理后,能使客户端与非HTTP协议的服务进行通信
- 隧道:隧道不会去处理HTTP请求,只会在客户端和服务端通过加密等手段建立安全的通信线路
2.HTTP是无状态的协议,引入cookie技术管理状态
使用HTTP协议,每当有新的请求发送时,就会产生新的响应,不会保留之前的请求或者响应的一切信息。但是在使用中经常有需要保存状态的场景,比如识别是否登录状态,识别发送请求的用户身份。于是引入了Cookie技术。作用原理:
- 客户发送请求,把用户名和密码等登录信息发送给服务器
- 服务收到登录信息后进行验证,然后把认证状态和sessionID绑定记录在后端,在响应时候响应头中带有写入session ID的Set-Cookie字段
- 客户端收到响应后,有set-cookie字段,会保存或者更新本地的cookie,下次发请求给服务端时候,会自动带上cookie信息发送给服务端,服务端就可以通过cookie字段里面的信息识别用户和用户的认证状态
3.HTTP协议的支持持久连接
在早期的时候每进行一次HTTP通信就要进行一次TCPL连接,下次再进行就又要开始一次TCP的连接,随着web技术的发展,大量的文字图片等内容需要传递和通信,所以每一次都要进行TCP连接就不能满足了,不仅让服务器负载压力大,http请求请求等也会很慢
因此自1999年的HTTP/1.1版本中增加了HTTP keep-alive即持久连接功能,只要建立连接后可多次发送HTTP请求,直到断开连接
三 HTTP报文和状态码
1.HTTP请求报文和响应报文
现在很多项目都前后端分离了,前后端对请求和响应应该是非常熟悉的,
请求报文
请求报文包含请求头和内容主体部分,请求头包含请求行(请求方法,url, http版本)和请求首部字段
(摘自:《图解HTTP》)
响应报文 响应报文也包含响应头和响应内容主题部分,响应头由响应行(HTTP版本、状态码)和响应首部字段组成组成
(摘自:《图解HTTP》)
首部字段
首部字段有很多,各有各的用处,有请求首部字段和响应首部字段,熟悉常用的字段的含义,不常见的可以查阅相关文档即可,这里就不再细说了。下图截图web网站中一个请求的请求首部字段
cookie相关首部字段
cookie技术虽然没有被编入标准化RFC中,但是得到了广泛的应用,为cookie服务的首部字段就两个
- set-cookie: 响应首部字段,服务器把相关认证信息放到set-cookie中,发送给客户端后,客户端更新本 地保存的cookie
- cookie:请求首部字段,客户端发送请求的时候自动携带上本地保存的cookie值发送给服务器
cookie字符串一般由属性名=xxx;的形式组成。例如
Set-Cookie: status=enable; expires=Tue, 05 Jul 2011 07:26:31,set-cookie字段的属性值含义如下:
2.HTTP响应的状态码
响应码也叫状态码,服务器响应客户端的请求时,使用状态码来描述返回的处理结果。状态码可以分为下面几大类
(摘自:《图解HTTP》)
具体的一些经常使用的状态码:
-
200:请求成功
-
204:请求成功,但是响应只有响应头没有响应内容
-
206:客户端执行的是范围请求,服务端成功执行
-
301:永久性重定向,请求的资源地址的url已经变更了
-
302:暂时性重定向,请求的资源暂时被分配了新的url
-
303: 与302功能一样,并且表示客户端应使用GET方法访问另外一个URI
-
304:告诉客户端,所请求的内容距离上次访问并没有变化. 客户端可以直接从浏览器缓存里获取该资源
-
400:语法错误,服务器无法解析
-
401:表示发送的请求需要认证或者认证失败过期等
-
403: 服务器拒绝提供服务,不允许访问
-
404: 服务器上没有请求的资源
-
500: 服务器内部执行过程中出现了错误
-
503: 服务器当前无法处理请求.这个状况是临时的,并且将在一段时间以后恢复.如果能够预计延迟时间,那么响应中可以包含一个Retry-After:头用以标明这个延迟时间.如果没有给出这个Retry-After:信息,那么客户端应当以处理500响应的方式处理它
四 HTTPS = HTTP + 加密 + 认证 + 完整性保护
上面我们简单了解了HTTP协议,然后目前HTTP还有一些不足之处,比如:
- 通信使用明文(不加密),内容很容易被窃听
- 不验证通信方的身份,因此有可能遭遇伪装
- 无法证明通信报文的完整性,所以报文有可能已遭篡改
对HTTP加上加密处理和通方的认证和内容的完整性保护后,就是HTTPS了,HTTPS并非一种新的协议,只是在http和TCP通信接口部分增加了SSL和TLS协议,在采用SSL后,HTTP就拥有了加密,证书和完整性保护的这些功能了。
(摘自:《图解HTTP》)
但值得注意的是:SSL是独立于HTTP协议的,其他运行在应用层的协议也可以配合SSL协议使用,可以说SSL是目前应用最广泛的网络安全技术
(摘自:《图解HTTP》)
1.加密和传送密钥
加密有两种方式
- (1)通信的加密,建立安全的通信线路后进行HTTP通信
- (2)对通信内容加密。 目前web服务中主要是对内容进行加密,对内容加密后要求通信方同时具备加密和解密的机制。
共享密钥加密:
加密和解密使用同一个密钥的方式称为共享密钥加密,也叫做对称密钥加密,以这种方式加密后,必须密钥也发送给对方后,对方才能对内容进行解密。那么怎么保证密钥安全地传递给对方不被窃取呢,因此有了两把密钥的公开密钥加密方式
公开密钥加密方式
公开密钥使用一对非对称的密钥,一把是私有密钥,一把是公开密钥,顾名思义,私有密钥自己保管。不能让别人知道,公开密钥对外公开。
通信时,发送方使用对方的公开密钥对内容进行加密处理后发送给对方,对方接收到加密的内容后使用自己的私有密钥进行解密,这样就很好地解决了密钥传输的问题而且目前要想根据密文和公开信息尝试恢复到原文信息是比较难的。
但是问题是如何确定公开密钥的正确性呢,可以使用由数字证书认证机构和其相关机构办颁发的公开密钥证书。服务商向认证机构提出公开密钥的申请,数字签名的认证机构在确认申请者的身份后,会对已申请的公开密钥进行数字签名,并将公钥密钥放入公钥证书后绑定在一起发送给客户端,客户端收到后就可以对证书上面的数字签名进行验证,验证通过后说明该公开密钥是值得新信赖的。但是如何安全地把颁发的公开密钥安全地转交给客户端也是一件困难的事情,因此多数客户端开发商(比如浏览器)都会事先植入常用的认证机关的公开密钥
HTTPS采用共享密钥加密和公开密钥加密两者并用的混合加密机制
因为公开密钥加密的方式相比于共享密钥加密方式,处理速度要慢一些。所以结合两者的优势,在交换密钥的阶段使用公开密钥加密的方式安全地传递给对方,之后就采用对称加密的方式进行通信。
(摘自:《图解HTTP》)
2.通信方身份的认证
SSL使用证书来确定通信方的身份,证书是由数字证书认证机构。一般我们称之为CA证书。上文我们说了,多数客户端开发商(比如浏览器)都会事先植入常用的认证机关的公开密钥。客户端使用CA的公开密钥对服务器发送过来的证书进行相关验证,验证通过,则说明该证书就是相应的服务端发过来的。否则就是非法证书。
3.确保通信内容的完整信
HTTPS在应用层会发送数据是会附加发送一种叫做MAC的报文摘要,摘要采用单项Hash函数将需要加密的明文“摘要”成一串固定长度(128位)的密文,而且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致。
接收者接收到数据后,使用HASH函数对收到的原文产生一个摘要信息,然后与解密后的发送者发送过来的摘要进行对比,如果相同说明收到的信息内容是完整的,在传输过程中没有被修改。从而验证了数据的完整性。
对于非常重要的保密数据,服务端还需要对客户端进行验证,以保证数据传送给了安全的合法的客户端。也是通过要求客户端发送证书来进行验证。比如,网上银行的u盾里面就包含有验证客户身份的数字签名证书
小结
以上是看了图解HTTP这本书结合自己思考,参考了其他的文章做的一篇总结,主要是想从前端角度认识客户端和服务端的通信过程,和真正的网络大佬相比,写的不是那么深入。求轻喷,如果有不对的地方,欢迎大家指正
参考文章