IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 网络-软件架构设计 -> 正文阅读

[网络协议]网络-软件架构设计

概述

网络协议有很多种,但对互联网来说,用的最多的就是HTTP协议。HTTP主要有1.0、1.1、2三个版本,在HTTP之上有HTTPS。
1996年,HTTP1.0协议规范RFC 1945发布;
1999年,HTTP1.1协议规范RFC 2616发布。
2015年,HTTP/2协议规范RFC 7540/7541发布。
HTTP/2还比较新,目前远没有达到普及的程度。在过去的近20年间,主流的协议一直是http1.1。接下来将对HTTP协议的发展脉络进行梳理。

HTTP1.0

HTTP1.0的问题

HTTP协议的基本特点是“一来一回”。什么意思呢?客户端发起一个TCP连接,在连接上面发一个HTTP Request到服务器,服务器返回一个HTTP Response,然后连接关闭。每来一个请求,就要开一个连接,请求完了,连接关闭。
这样的协议有两个问题:

  1. 性能问题。连接的建立、关闭都是耗时操作。对应一个网页来说除了网页本身的HTML请求,页面里面的JS、CSS、img资源,都是一个个的HTTP请求。现在的互联网上的页面,一个页面上有几十个资源文件是很常见的事。每来一个请求就开一个TCP连接时非常耗时的。虽然可以同时开多个连接,并发的发送请求,但连接数毕竟是有限的。
  2. 服务器推送问题。不支持“一来多回”,服务器无法在客户端没有请求的情况下主动向客户端推送消息。但很多的应用恰恰都需要服务器在某些事情完成后主动通知客户端。
    针对这两个问题,来看HTTP在发展过程中是怎么解决的。

Keep-Alive机制与Content-Length属性

为了解决上面提及的第一个问题,HTTP1.0设计了一个Keep-Alive机制来实现TCP连接的复用。具体来说,就是客户端在HTTP请求的头部加上一个字段Connection:Keep-Alive。服务器收到带有这样字段的请求,在处理完请求之后不会关闭连接,同时在HTTP的Response里面也和加上该字段,然后等待客户端在该连接上发送下一个请求。
当然,这会给服务器带来一个问题:连接数有限。如果每个连接都不关闭的话,一段时间之后,服务器的连接数就耗光了。因此,服务器会有一个Keep-Alive timeout参数,过一段时间之后,如果该链接上上没有新的请求进来,则连接就会关闭。
连接复用之后又产生了一个新问题:以前一个连接就只发送一个请求,返回一个响应,服务器处理完毕,把连接关闭,这个时候客户端就知道连接的请求处理结束了。但现在,即使一个请求处理完了,连接也不关闭,那么客户端怎么知道连接处理结束了呢?或者说,客户端怎么知道接收回来的数据包是完整的呢?
答案是在HTTP Response的头部,返回一个Content-Length:xxx的字段,这个字段可以告诉客户端HTTP Response的Body共有多少个字节,客户端接收到这么多字节之后,就知道响应成功接收完毕。

HTTP 1.1

连接复用与Chunk机制

从上面的分析可以看出,连接复用非常有必要,所以到了HTTP 1.1之后,就把连接复用变成了一个默认属性。即使不加Connection:Keep-Alive属性,服务器也会在请求处理完毕之后不关闭连接。除非在请求头部显示地加上Connection:Close属性,服务器才会在请求处理完毕之后主动关闭连接。
在HTTP 1.0里面可以利用Content-Length字段,让客户端判断一个请求的响应成功是否接收完毕。但Content-Length有个问题,如果服务器返回的数据时动态语言生成的内容,则要计算Content-Length,这点对服务器来说比较困难。即使能够计算,也需要服务器在内存中渲染出整个页面,然后计算长度,非常耗时。
为此,在HTTP1.1中引用了Chunk机制(Http Streaming)。具体来说,就是在响应的头部加上Transfer-Encoding:chunked属性,其目的是告诉客户端,响应的Body是分成一块块的,块与块之间有分隔符,所有块的结尾也有一个特殊标记。这样,即使没有Content-Length字段,也能方便客户判断出响应的末尾。
下面显示了一个简单的具体Chunk机制的HTTP响应,头部没有Content-Length字段,而是Transfer-Encoding:chunked字段。该响应包含4个chunk,数字25(16机制)表示第一个chunk的字节数,1C(16进制)表示第二个chunk的字节数…最后的数字0表示整个响应的末尾。

HTTP/1.1 200 OK
Content-Type:text/plain
Transfer-Encoding:chunked
25
This is the data in the first chunk
1C
and this is the second one
3
con
8
sequence
0

Pipeline与Head-of-line Blocking问题

有了“连接复用”之后,减少了建立连接、关闭连接的开销。但还存在一个问题,在同一个连接上,请求是串行的,客户端发送一个请求,收到响应,然后发送下一个请求,再收到响应。这种串行的方式导致并发度不够。
为此,HTTP1.1引入了Pipeline机制。在同一个TCP连接上面,可以在一个请求发出去之后、响应没有回来之前,就可以发送下一个、再下一个,这样就提高了在同一个TCP连接上面的处理请求的效率。如下图所示,展示了在同一个TCP连接上面,串行和Pipeline的对比。
在这里插入图片描述
从上图可以明显看出,Pipeline提高了请求的处理效率。但Pipeline有个致命问题,就是Head-of-Line Blocking翻译成中文叫做“对头阻塞”。什么意思呢?
客户端发送的请求顺序是1,2,3,虽然服务器是并发处理的,但客户端端接收响应的顺序必须是1,2,3,如此才能把响应和请求成功匹对,跟队列一样,先进先出。一旦队列头部请求1发生延迟,客户端迟迟收不到请求1的响应,则请求2、请求3响应也会被阻塞。如果请求2、请求3不和请求3在一个TCP连接上面,而是在其他的TCP连接上面发出去的话,说不定早返回了,现在因为请求1处理的慢,也影响了请求2、请求3。
也正因为如此,为了避免Pipeline带来的副作用,很多浏览器默认把Pipeline关闭了。

HTTP/2出现之前的性能提升方法

HTTP/2

TCP协议是先进先出的协议。
报文段在一个TCP连接上,如果按照seq=1,seq=2,seq=3的顺序发送到服务器,服务器端必定是按照seq=1,seq=2,seq=3的顺序接收报文段。如果过程中seq=1的数据包延迟或者丢包,服务端会一直等待seq=1的包。
因为报文有seq和ack序号,比如服务端发送一个包ack=1,那么客户端发送的包seq=1必须先到服务端,之后的seq=2的包才能被服务端接收,这就是TCP协议的报文先进先出规则,这注意是为了放置丢包等问题。

SSL/TLS

在介绍HTTPS之前,需要先深入探讨SSL/TLS,因为HTTPS是构建在这个基础上的。

背景

SSL/TLS的历史几乎互联网历史一样长:SSL(Secure Socket Layer)的中文名词为安全套接层,TLS(Transport Layer Security)的中文名词为传输层安全协议。
1994年,网景(NetScape)公司设计了SSL1.0;
1995年,网景公司发布SSL2.0,但很快发现存在严重漏洞;
1996年,SSL3.0问世,得到大规模应用;
1999年,互联网标准化组织IETF对SSL进行标准化,发布了TLS1.0;
2006年和2008年,TLS进行了两次升级,分别为TLS1.1和TLS1.2。
所以,TLS1.0相当于SSL3.1;TLS1.1、TLS1.2相当于SSL3.2、SSL3.3。在应用层里,习惯将两者并称为SSL/TLS。
如下图,SSL/TLS处在TCP层的上面,它不仅可以支撑HTTP协议,也能支撑FTP、IMAP等其他各种应用层的协议。
在这里插入图片描述
接下来从最基础的对称加密讲起,一步步分析SSL/TLS背后的原理和协议本身。

对称加密的问题

对称加密的想法很简单,如下图所示。客户端和服务器知道同一个密钥,客户端给服务器发消息,客户端用此密钥加密,服务器用此密钥解密;反过来,服务器给客户端发消息时,是相反的过程。
在这里插入图片描述
这种加密方式在互联网上有两个问题:

  • 密钥如何传输?
    密钥A的传输也需要另外一个密钥B,密钥B的传输有需要密钥C…,如此循环,无解。
  • 如何存储密钥?
    对应浏览器的网页来说,都是明文的,肯定存储不了密钥;对应Android/iOS客户端,即使能把密钥藏在安装包的某个位置,也很容易被破解。
    当然,这两个问题其实是一个问题。因为如果解决了密钥的传输问题,就可以在建立好连接之后获取到密钥,然后只存在内存中,当连接断开之后,密钥在内存中就被销毁了,也就解决了存储的问题。

双向非对称加密

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-12-23 16:03:14  更:2021-12-23 16:04:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年10日历 -2024/10/5 7:42:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码