HTTP

http是目前应用最广泛的应用层协议,截止到目前为止已经发布了多个版本,最常用的是http1.1和http2。

http0.9是最早的版本,功能很简单,没有header,只支持GET。

http1.0

  • 只支持短连接,即每次请求一个资源就会新建一次tcp连接,服务器写完响应行后立刻将TCP连接关闭

    由于tcp连接的建立和关闭需要经历三次握手和四次握手,再加上tcp慢启动特性,报文一开始不会满负荷传输,所以不仅开销很大,而且效率很低。

  • 相比于上一版本,增加了http header,和status code用于声明请求的结果,content-type字段也可以用来声明传输其他文件,头部还增加了协议的版本号。

http1.1是1997年发布的,是现在使用最广泛的版本,这个版本引入了长连接,减少了tcp连接建立和关闭的消耗。

  • 新加了connection请求头字段,false表示短连接,keep-alive表示长连接(默认)

    在持久连接模式中,由于服务器不会立刻关闭TCP连接,所以需要在响应中加上一个Content-Length的响应头来表示响应体的长度,让浏览器判断HTTP响应是否结束。如果没有这个响应头的话,浏览器会处于pending的状态,因为在它看来还有数据要接收。

    所以长连接无非就是通过Content-Length字段把连接关闭的主动权交给了客户端。

  • 支持分块传输编码,可以发送动态数据,只在1.1版本中可以使用

    使用分块传输编码,数据分解成一系列数据块,并以一个或多个块发送,这样服务器可以发送数据而不需要预先知道发送内容的总大小,使得服务器可以发送动态生成的数据。

    设置相应头Transfer-Encoding:chunked,此时消息体便由数量未定的块组成,并以最后一个大小为0的块结束。

    HTTP/1.1 200 OK\r\n
    \r\n
    Transfer-Encoding: chunked\r\n
    ...\r\n
    \r\n
    <chunked 1 length>\r\n
    <chunked 1 content>\r\n
    <chunked 2 length>\r\n
    <chunked 2 content>\r\n
    ...\r\n
    0\r\n
    \r\n
    \r\n

其他的改变还有增加了Host头,让服务端知道用户请求的是哪个域名等。

2014年,更新了内容,增加了TLS支持,即https传输,除了短连接和长连接模型,还支持服务端push模型,websocket模型。

Http2是2015年发布的,主要就是提升安全性与性能,gRPC底层就是使用的http2协议。

  • 多路复用(Multiplexing):就是说 HTTP/2 可以重复使用同一个 TCP 连接,并且连接是多路的,多个请求或响应可以同时传输,这也是gRPC支持客户端流和服务器端流的原因

    • 对比之下,HTTP/1.1 的长连接也能复用 TCP 连接,但是只能串行,不能“多路”。

    • Rest API通常构建在http1.1上,是请求响应模式。如果一个微服务收到多个客户端请求,每次只能处理一个,即使构建在http2上,依旧是请求响应模式,无法发挥http2的优势:多路复用。

      gRPC构建在http2上,支持流式通信和双向通信,通过不断流式传输信息同时处理这些请求。但双向流模式依旧需要客户端发起调用。这里的流式通信,不是全双工的,只是将原本的请求响应风格,变为了同时可以发送多个请求,服务器也能发送多个响应。

  • 二进制协议:HTTP/2 的消息头使用二进制格式,而非文本格式。并且使用专门设计的 HPack 算法压缩。

  • 服务器推送:服务端能够直接把资源推送给客户端,当客户端需要这些文件的时候,它已经在客户端了。(HTTP/2推送服务器只能被浏览器来处理,而不是应用)

  • 通讯双方cache一份header filed表,用来差量更新头部字段,避免重复header的传输

HTTP3

2018年发布,基于谷歌的QUIC,底层使用udp代码tcp协议,

这样解决了队头阻塞问题,同样无需握手,性能大大地提升,默认使用tls加密。

WebSocket

websocket是一个双向通信协议,它在握手阶段采用http1.1

握手过程

  1. 发起握手请求

    HTTP/1.1 101 Switching Protocols  // 状态行
    Upgrade: websocket // required
    Connection: Upgrade // required
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= // required,加密后的 Sec-WebSocket-Key
    Sec-WebSocket-Protocol: chat // 表明选择的子协议
  2. 服务器如果支持websocket,返回101响应

    HTTP/1.1 101 Switching Protocols  // 状态行
    Upgrade: websocket // required
    Connection: Upgrade // required
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= // required,加密后的 Sec-WebSocket-Key
    Sec-WebSocket-Protocol: chat // 表明选择的子协议

WebSocket 提供两种协议:不加密的 ws:// 和 加密的 wss://. 因为是用 HTTP 握手,它和 HTTP 使用同样的端口:ws 是 80(HTTP),wss 是 443(HTTPS)

HTTP2 vs WebSocket

WebSocket是全双工的,可以双向通信,主要应用在实时通信的场景中,服务器可以实时推送数据给客户端。

HTTP/2 虽然也支持 Server Push,但是服务器只能主动将资源推送到客户端缓存!那不是应用程序可以感知的,主要是让浏览器(用户代理)提前缓存静态资源。

在典型的HTTP 1.x工作流中,浏览器请求一个页面,服务器在响应中返回一个HTML,然后就时等待浏览器解析响应并发送额外请求来获取额外的内嵌资源(JavaScript、CSS等)。服务器推送使服务器能够试探性地向客户端发送资源。此时,浏览器不必解析HTML页面并找到需要加载的其它资源;而是服务器能够立即开始发送它们。

但是人类的想象力是非常丰富的。比如为了让服务器可以推送消息给客户端,使用了一个“偏方”。它就是SSE(Server Sent Event)。SSE是一种让服务器能够在客户端服务器建立连接之后异步推送数据给客户端的机制。由于SSE是基于HTTP的,其天然适配于HTTP/2,这样SSE就可以集两者之长:HTTP/2可以基于多路复用流形成一个高效传输层,同时SSE给应用提供了API使之能够进行推送。

Websocket技术可能会继续使用,但是SSE和其EventSource API同HTTP/2的能力相结合可以在多数场景下达到同样的效果,但是会更简单。

HTTP2和WebSocket的更多相关文章

  1. Android okHttp网络请求之Get/Post请求

    前言: 之前项目中一直使用的Xutils开源框架,从xutils 2.1.5版本使用到最近的xutils 3.0,使用起来也是蛮方便的,只不过最近想着完善一下app中使用的开源框架,由于Xutils里 ...

  2. Android网络框架比较

    今天,公司需要为一个安卓app选择一个合适的网络框架,具体我了解,主要的安卓网络框架有okhttp,retrofit,android-async-http,volley. 查找网上的资料,大致可以得到 ...

  3. Jetty 9.3庆祝20周年生日快乐,并添加HTTP/2支持

    本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2015/06/Building-Distributed-Systems 今年6月12日 ...

  4. channels 2.x的使用

    转载:https://www.vimiix.com/post/2018/07/26/channels2-tutorial/ 认识 Channels 之前,需要先了解一下 asgi ,全名:Asynch ...

  5. [转载]前端 阿里p6面试题集锦含答案

    1.说一下你了解CSS盒模型. 盒模型分为:IE的怪异盒模型和标注浏览器的盒模型,然后可以通过box-sizing属性控制两种盒模型的变换. 2.说一下box-sizing的应用场景. 这个也不难,简 ...

  6. 3月web前端面试小结

    说一下box-sizing的应用场景 box-sizing的属性值分为两个,border-box和content-box,其中, border-box:width=content+padding+bo ...

  7. jdk11新特性

    JDK 11主要特性一览 jdk11即将在9月25号发布正式版.确定的新特性包括以下17个 181 嵌套类可见性控制 309 动态文件常量 315 改进 Aarch64 Intrinsics 318 ...

  8. 详解golang net之transport

    关于golang http transport的讲解,网上有很多文章读它进行了描述,但很多文章讲的都比较粗,很多代码实现并没有讲清楚.故给出更加详细的实现说明.整体看下来细节实现层面还是比较难懂的. ...

  9. HttpCanary——最强Android抓包工具!

    迎使用HttpCanary——最强Android抓包工具! HttpCanary是一款功能强大的HTTP/HTTPS/HTTP2网络包抓取和分析工具,你可以把他看成是移动端的Fiddler或者Char ...

随机推荐

  1. [BUUCTF]PWN——CmmC_Simplerop

    cmcc_simplerop 附件 步骤 例行检查,32位,开启了nx保护 本地试运行一下程序,查看一下大概的情况 32位ida载入,习惯性的检索程序里的字符串,看了个寂寞,从main函数开始看程序 ...

  2. 使用批处理文件(.bat)启动多个CMD窗口并执行命令

    由于每次启动本机的kafka都需要打开2个cmd窗口,分别启动zookeeper服务和kafka服务,操作相对繁琐,于是想起了批处理来帮忙一键启动. 在桌面新建一个txt文件,改后缀名为.bat,并加 ...

  3. CF999B Reversing Encryption 题解

    Content 给一个长度为 \(n\) 的字符串 \(s\),执行以下操作: 降序遍历 \(n\) 的所有因子(从 \(n\) 到 \(1\)). 对于每一个因子 \(i\) 翻转字符串 \(s_{ ...

  4. java 理论基础 类的初始化(加载、连接(验证、准备、解析)、初始化)

    一个进程就有一个JVM,每个进程之间资源独立 当调用java命令来启动某个Java程序的时候,该命令创建一个独立的进程来运行我们的Java程序.而这个独立的进程里面就包含一个Java虚拟机.不管该程序 ...

  5. java 网络编程基础 InetAddress类;URLDecoder和URLEncoder;URL和URLConnection;多线程下载文件示例

    什么是IPV4,什么是IPV6: IPv4使用32个二进制位在网络上创建单个唯一地址.IPv4地址由四个数字表示,用点分隔.每个数字都是十进制(以10为基底)表示的八位二进制(以2为基底)数字,例如: ...

  6. Linux(centos7)安装redis并设置redis开机自启动

    1.下载redis安装包 wget http://download.redis.io/releases/redis-4.0.6.tar.gz 2.解压安装包 tar -zxvf redis-4.0.6 ...

  7. Subsequence(hdu3530)

    Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  8. <学习opencv>绘画和注释

    /*=========================================================================*/ // 绘画 和 注释 /*========= ...

  9. Java初学者作业——编写 Java 程序,在控制台中输入日期,计算该日期是对应年份的第几天。

    返回本章节 返回作业目录 需求说明: 编写 Java 程序,在控制台中输入日期,计算该日期是对应年份的第几天. 实现思路: (1)声明变量 year.month和 date,用于存储日期中的年.月.日 ...

  10. Lombok的利弊

    1.介绍 Lombok是一个可以大量减少代码的工具, 通过Pluggable Annotation Processing API的方式解析注解, 在编译期为class文件注入getter,setter ...