这个专栏的计算机网络协议,我是在极客时间上学习 已经有三万多人购买的刘超老师的趣谈网络协议专栏,讲的特别好,像看小说一样学习到了平时很枯燥的知识点,计算机网络的书籍太枯燥,感兴趣的同学可以去付费购买,绝对物超所值,本文就是对自己学习专栏的总结,评论区可以留下你的问题,咱们一起讨论!
上一篇文章中介绍了常见的传输层的协议,接下来开始讲应用层的协议。本文将分为三个协议给大家进行介绍:
http://www.taobao.com 是个URL,叫作统一资源定位符;
HTTP请求的准备
系统会将http://www.taobao.com 提交给DNS服务器解析为IP地址;
目前使用的HTTP协议大部分都是1.1,默认开启Keep-Alive,建立起的TCP连接可以在多次请求中复用;
HTTP请求的构建
建立连接之后,浏览器发送HTTP的请求,请求格式如下:
HTTP分为三部分:请求行、首部、正文实体;
第一部分:请求行
在请求行中,URL就是 http://www.taobao.com ,版本为HTTP 1.1,方法有几种类型:
GET
GET就是去服务器获取一些资源,可以返回的是一个网页,也有许多别的格式,比如说返回一个JSON字符串;
POST
需要主动告诉服务端一些信息,一般会放在正文里面。正文可以有各种各样的格式。常见的格式也是JSON;
PUT
向指定资源位置上传最新内容,POST往往是用来创建一个资源的,而PUT往往是用来修改一个资源;
DELETE,删除资源,例如删除云主机;
第二部分:首部字段
首部是key value,通过冒号分隔,往往保存了一些非常重要的字段。例如,Accept-Charset,表示客户端可以接受的字符集,防止传过来的另外字符集导致乱码;
或者是Content-Type是指正文的格式,进行POST的请求,如果正文是JSON,那么我们就应该将这个值设置为JSON;
在HTTP头里面,Cache-control是用来控制缓存的。当客户端发送的请求中包含max-age指令时,如果判定缓存层中,资源的缓存时间数值比指定时间的数值小,那么客户端可以接受缓存的资源;当指定max-age值为0,那么缓存层通常需要将请求转发给应用集群。
If-Modified-Since也是一个关于缓存的,如果服务器在某段时间更新了就会下载最新资源,反之就会返回一个“304 Not Modifed”的响应;
HTTP请求的发送
HTTP协议是基于TCP,面向连接,通过stream二进制流的方式传给对方;
每发送一个报文,都需要对方有一个回应ACK,保证报文可靠传到了对方;
TCP层每发送一个报文,就会在IP头加上源地址和目标地址,交给IP层进行传输;
IP层和目标地址在一个局域网,就发送ARP协议来请求这个目标地址对应的MAC地址,然后将源MAC和目标MAC放入MAC头,发送出去即可;不在同一个局域网,就需
要发送到网关,还要需要发送ARP协议,来获取网关的MAC地址,然后将源MAC和网关MAC放入MAC头,发送出去;
网关收到包发现MAC符合,取出目标IP地址,根据路由协议找到下一跳的路由器,获取下一跳路由器的MAC地址,将包发给下一跳路由器。路由器一跳一跳终于到达目标的局域网后,找到目标机器的MAC地址进行匹配;;发现IP地址符合,根据IP头中协议项,知道自己上一层是TCP协议,于是解析TCP的头,里面有序列号,需要看一看这个序列包是不是我要的,如果是就放入缓存中然后返回一个ACK,如果不是就丢弃。
HTTP的服务器正在监听TCP的端口号,目标机器返回对应的包发送给HTTP服务器,最终就将想要看到的网页传到客户端;
HTTP返回的构建
HTTP的返回报文也是有一定格式的,基于HTTP 1.1;
构造好了返回的HTTP报文,接下来就是把这个报文发送出去。还是交给Socket去发送,还是交给TCP层,让TCP层将返回的HTML,也分成一个个小的段,并且保证每个段都可靠到达。
这些段加上TCP头后会交给IP层,然后把刚才的发送过程反向走一遍。虽然两次不一定走相同的路径,但是逻辑过程是一样的,一直到达客户端。客户端发现MAC地址符合、IP地址符合,于是就会交给TCP层。根据序列号看是不是自己要的报文段,
如果是,则会根据TCP头中的端口号,发给相应的进程。这个进程就是浏览器,浏览器作为客户端也在监听某个端口。
当浏览器拿到了HTTP的报文。发现返回“200”,一切正常,于是就从正文中将HTML拿出来。HTML是一个标准的网页格式。浏览器只要根据这个格式,展示出一个绚丽多彩的网页。
HTTP/1.x 缺陷
HTTP/1.x 实现简单是以牺牲性能为代价的:
客户端需要使用多个连接才能实现并发和缩短延迟;
不会压缩请求和响应首部,从而导致不必要的网络流量;
不支持有效的资源优先级,致使底层 TCP 连接的利用率低下
HTTP 2.0会对HTTP的头进行一定的压缩,将原来每次都要携带的大量key value在
两端建立一个索引表,对相同的头只发送索引表中的索引;
HTTP 2.0协议将一个TCP的连接中,切分成多个流,每个流都有自己的ID,而且流可以是客户端发往服务端,也可以是服务端发往客户端。它其实只是一个虚拟的通道。流是有优先级的。
HTTP 2.0还将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。
Header帧用于传输Header内容,并且会开启一个新的流;
Data帧用来传输正文实体,多个Data帧属于同一个流;
通过这两种机制,HTTP 2.0的客户端可以将多个请求分到不同的流中,然后将请求内容拆成帧,进行二进制传输。这些帧可以打散乱序发送, 然后根据每个帧首部的流标识符重新组装,并且可以根据优先级,决定优先处理哪个流的数据;
HTTP 2.0成功解决了HTTP 1.1的队首阻塞问题,同时,也不需要通过HTTP 1.x的pipeline机制用多,条TCP连接来实现并行请求与响应;减少了TCP连接数对服务器性能的影响,同时将页面的多个数据css、js、 jpg等通过一个数据链接进行传输,能够加快页面组件的传输速度。
总结
用HTTP协议看个新闻倒是没啥问题,但是假如你要是在网页中下单购物,黑客截获了你的支付请求,就可以骗取你的银行卡和密码;
一般能想到的思路就是加密
加密分为:
对称加密:
对称密钥加密(Symmetric-Key Encryption),加密和解密使用同一密钥。
优点:运算速度快;
缺点:无法安全地将密钥传输给通信方
比如:你和淘宝之间各自约定一个密钥,采用密钥加密传输,淘宝采用这个密钥解密,黑客截获你的请求,也破解不了;
存在的问题就是 你如何同淘宝之间约定同一个密钥,如果这个密钥在网络中传输,会被黑客截获的,总不能像谍战剧一样线下传输,约定同一个密钥,这对于大型互联网公司是不可能的;
常见的对称加密算法:
非对称加密
非对称密钥加密,又称公开密钥加密(Public-Key Encryption);加密和解密使用不同的密钥。
公开密钥所有人都可以获得,通信发送方获得接收方的公开密钥之后,就可以使用公开密钥进行加密,接收方收到通信内容后使用私有密钥解密。
非对称密钥除了用来加密,还可以用来进行签名。因为私有密钥无法被其他人获取,因此通信发送方使用其私有密钥进行签名,通信接收方使用发送方的公开密钥对签名进行解密,就能判断这个签名是否正确。
常见的非对称加密算法
数字证书
不对称加密一般通过放在公网地址上让对方下载,另一种就是在建立连接的时候,传给对方;
例如:通过以下命令创建一个私钥
openssl genrsa -out cliu8siteprivate.key 1024
再根据这个私钥,创建对应的公钥:
openssl rsa -in cliu8siteprivate.key -pubout -outcliu8sitepublic.pem
这个时候就需要权威部门的介入,就像你的户口本上只要公安局盖章之后,才能证明是你,由权威部门颁发的称为证书(Certificate);
证书(Certificate)中包含公钥、证书的所有者、证书的发布机构和证书的有效期;
证书的生成需要权威机构去认证,就是CA( Certificate Authority);
采用以下命令
openssl req -key cliu8siteprivate.key -new -out cliu8sitecertifcate.req
数字证书认证机构(CA,Certificate Authority)是客户端与服务器双方都可信赖的第三方机构;要想验证证书,需要CA的公钥,,CA的公钥也需要更牛的CA给它签名,然后形成CA的证书。就像你不相信区公安局,可以打电话问市公安局,让市公安局确认区公安局的合法性。这样层层上去,直到全球皆知的几个著名大CA,称为rootCA,做最后的背书。通过这种层层授信背书的方式,从而保证了非对称加密模式的正常运转。
服务器的运营人员向 CA 提出公钥的申请,CA 在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公开密钥证书后绑定在一起。
进行 HTTPS 通信时,服务器会把证书发送给客户端。客户端取得其中的公开密钥之后,先使用数字签名进行验证,如果验证通过,就可以开始通信了。
HTTPS的工作模式
当你登录一个外卖网站的时候,由于是HTTPS,客户端会发送Client Hello消息到服务器,以明文传输TLS版本信息、加密套件候选列表、压缩算法候选列表等信息。另外,还会有一个随机数,在协商对称密钥的时候使用。
类似于,“您好,我要订外卖,但你要加密我要吃的饭,再给你一个随机数留着”
外卖网站返回一个回Server Hello消息, 告诉客户端,服务器选择使用的协议版本、加密套件、压缩算法等,也会有一个随机数,用于后续的密钥协商。
类似于,“您好,保密没问题,你的加密套路还挺多,咱们就按套路2来吧,我这里也有个随机数,你也留着。”
然后外卖网站会给你一个证书,如果你不信任这个证书就拿自己信任的CA库中的CA证书的公钥去解密外卖网站的证书,成功即为可信的CA,反之不断地回溯CA,直到找到一个授信地CA即可;
证书验证完毕之后,觉得这个外卖网站可信,于是客户端计算产生随机数字Pre-master,发送Client Key Exchange,用证书中的公钥加密,再发送给服务器,服务器可以通过私钥解密出来。
目前为止,无论是客户端还是服务器,都有了三个随机数,分别是:自己的、对端的,以及刚生成的Pre-Master随机数。通过这三个随机数,可以在客户端和服务器产生相同的对称密钥。
有了对称密钥,后面就可以协商通信密钥和加密算法进行加密通信了。
总结
最简单就是通过过HTTP进行下载,文件一大,速度就很慢;
还可以通过FTP,也即文件传输协议,FTP有两种工作模式,分别为主动模式(PORT)和被动模式(PASV)
无论是HTTP的方式,还是FTP的方式,都难以解决单一服务器的带宽压力,因为它们都是采用的传统的客户端服务器的方式;
P2P就是peer-to-peer,资源开始并不集中地存储在某些设备上,而是分散地存储在多台设备上。这些设备我们姑且称为peer。
想要下载一个文件的时候,你只要得到那些已经存在了文件的peer,并和这些peer之间,建立点对点的连接,而不需要到中心服务器上,就可以就近下载文件。一旦下载了文件,你也就成为peer中的一员,你旁边的那些机器,也可能会选择从你这里下载文件,所以当你使用P2P软件的时候,例如BitTorrent ,往往能够看到,既有下载流量,也有上传的流量,也即你自己也加入了这个P2P的网络,自己从别人那里下载,同时也提供给其他人下载。可以想象,这种方式,参与的人越多,下载速度越快,一切完美。
种子(.torrent)文件
.torrent文件由两部分组成,分别是:announce(tracker URL)和文件信息。
文件信息包含以下内容:
下载时,BT客户端会先解析.torrent文件得到tracker地址,连接到tracker服务器;trakcer服务器回应下载者的请求,并返回其它下载者的IP提供给下载者,根据.torrent文件交换双方已有的块,然后交换双方没有的数据;
每下载一个块,需要算出下载块的Hash验证码,并与.torrent文件中的对比;
这种方法的弊端是太依赖tracker服务器,一旦tracker服务器出现故障或者线路遭到屏蔽,BT工具就无法正常工作;
去中心化网络(DHT)
DHT(Distributed Hash Table)
每个加入这个DHT网络的人,都要负责存储这个网络里的资源信息和其他成员的联系信息,相当于所有人一起构成了一个庞大的分布式存储数据库。
DHT中有一个Kademlia协议
任何一个BitTorrent 启动之后,都会充当两个角色:
每个DHT node都有一个ID,是通过文件哈希计算出的索引(来知道某些文件保存在哪些节点中);
DHT算法:如果一个文件计算出一个哈希值,则和这个哈希值一样的那个DHT node,就有责任知道从哪里下载这个文件,即便它自己没保存这个文件。除了一模一样的那个DHT node应该知道,ID和这个哈希值非常接近的N个DHTnode也应该知道;
ID相似,在Kademlia网络中,距离是通过异或(XOR)计算的;
在这种模式下,种子.torrent文件里面就不再是tracker的地址了,而是一个list的node的地址,而所有这些node都是已经在DHT网络里面的。当然随着时间的推移,很可能有退出的,有下线的,但是我们假设,不会所有的都联系不上,总有一个能联系上。
DHT中按照距离分层,就像你的朋友圈一样 按照亲疏程度远近分层;
DHT网络中通过Kademlia的查询机制,二分查找,对于总节点数N,只需要查询log2(N)次,如下所示:
Kademlia算法中,每个节点只有4个指令:
DHT网络中网络如何更新?
总结