|
一. TCP三次握手与四次挥手
image.png
二. HTTP1.0
1.请求行
{请求方法} + {URL字段} + {HTTP协议版本} 们用空格分隔。
例如,GET /index.html HTTP/1.1。
HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。
2.请求头部
由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:
User-Agent:产生请求的浏览器类型。
Accept:客户端可识别的内容类型列表。
Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
请求头说明Host接受请求的服务器地址,可以是IP:端口号,也可以是域名User-Agent发送请求的应用程序名称Connection指定与连接相关的属性,如Connection:Keep-AliveAccept-Charset通知服务端可以发送的编码格式Accept-Encoding通知服务端可以发送的数据压缩格式Accept-Language通知服务端可以发送的语言
3.请求数据
请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length
三. HTTP1.1
HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议。 主要区别主要体现在:
1.缓存处理
在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
2.带宽优化及网络连接的使用
HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
3.长连接
HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启*Connection: keep-alive*,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
四. HTTP2.0
超文本传输协议第二版,2015年2月17日被批准。
与HTTP1.1区别:
1.采用二进制格式而非文本格式。
比起超文本协议,二进制协议解析起来更加高效,更紧凑,更重要的时错误更少。
二进制分帧:所有HTTP 2.0通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。每个数据流以消息的形式发送。而消息由一或多个帧组成,而这些帧可以乱序发送,然后再根据每个帧首部流标识符重新组装。
2.多路复用
HTTP1.x一个连接只能提交一个请求,效率比较高,但是多了就会变慢。
多路复用能很好的解决此问题。能同时处理多个消息的请求和响应。
3.报头压缩
多个请求,多个头部。HTTP2.0可以压缩头部,节省开销。
第一次需要传完整的请求头部,后面只要穿与第一次不一样的头部消息就ok
4.服务器推送
HTTP2.0让服务器可以将响应主动推送到客户端缓存中。
五. HTTP3.0
由于TCP和UDP两者在运输层存在一定差异,TCP的传递效率与UDP相比有天然劣势,于是Google基于UDP开发出了新的协议QUIC(Quick UDP Internet Connections),希望取代TCP提高传输效率,后经过协商将QUIC协议更名为HTTP/3。
谷歌决定在UDP基础上改造一个具备TCP协议优点的新协议也就顺理成章了,这个新协议就是QUIC协议。
六. Protobuffer存储原理
可变长编码。Protobuf 序列化后所生成的二进制消息非常紧凑,这得益于 Protobuf 采用的非常巧妙的 Encoding 方法。考察消息结构之前,让我首先要介绍一个叫做 Varint 的术语。
Varint 是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。
比如对于 int32 类型的数字,一般需要 4 个 byte 来表示。但是采用 Varint,对于很小的 int32 类型的数字,则可以用 1 个 byte 来表示。当然凡事都有好的也有不好的一面,采用 Varint 表示法, 大的数字则需要 5 个 byte 来表示。从统计的角度来说,一般不会所有的消息中的数字都是大数,因此大多数情况下,采用 Varint 后,可以用更少的字节数来表示数字信息。
优点:
1.性能方面
a.体积小
b.序列化速度快
c.传输速度快
2.使用方面
a.使用简单,proto编译器自动进行序列化和反序列化
b.维护成本低,多平台仅需维护一套协议文件(.proto)
c.向后兼容性好,不必破坏旧的数据格式,就可以对旧的数据格式进行更小。
d.加密性好,http抓包只能看到字节,不能看到真实数据。
3.使用范围方面。
a.跨平台
b.跨语言
c.可扩展性
缺点:
1.功能方面
不适用基于文本的标记文档建模。
2.其它方面
通用性差,如果需要与外部项目交互,建议不要使用。
自解释性差,以二进制流数据进行存储,需要通过proto文件才能看到。
总结:
protobuffer比xml,json更小更快,使用简单,维护简单,但就是行业通用性差。
七.例程
#Persion.protosyntax ="proto3";option java_package="com.maniu.protobufferdemo";option java_outer_classname="Person";import "Adress.proto";message _Person{ string name=1; int32 id=2; string eamil=3; bool isCheck=4; enum _PhoneType{ MOBILE=0; HOME=1; WORK=2; } message _PhoneNumber{ string number=1; _PhoneType type=2; } string card=5; repeated _PhoneNumber phone=6; _Adress adress=7;}public class MainActivity extends AppCompatActivity { private static final String TAG = "david"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);// 序列化 本身已经是序列化 Person._Person._PhoneNumber.Builder phoneNumberBuld = Person._Person._PhoneNumber. newBuilder().setNumber("110"); Person._Person.Builder personBuild=Person._Person.newBuilder().setCard("红色的汽车") .setEamil("105191735@qq.com").setIsCheck(true).addPhone(phoneNumberBuld).setName("david"); Person._Person person = personBuild.build(); Log.i("david", " name " + person.toString());// 反序列化 反序列化过程 byte[] bytes = person.toByteArray();// 反序列化 try { Person._Person person1 =Person._Person.parseFrom(bytes); Log.i("david", " name " + person1.toString()); Log.i(TAG, "onCreate4: "+person1.getCard()); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } }} |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|