OkHttp与HTTP协议
OkHttp,从名字也能感觉到这套框架似乎与http协议有着千丝万缕的关系。事实上也确实如此,OkHttp所做的各种操作都是建立在http协议基础之上的。因此在理解并自己手写OkHttp之前,首先需要了解什么是http协议,以及http协议具体有哪些规则(或者说是格式)
为什么需要http协议
一般情况下,网络数据由客户端向服务端发送,数据进入互联网之后,是以二进制流(Stream)的形式进行传播,过程如下图所示:
客户端浏览器访问网页 “www.sample.com” 并进行登录操作,需要向服务端发送用户名与密码;然后服务端接收到客户端的请求之后,对数据进行封装、解析并返回响应结果。
但是正如图中所示,客户端发送的数据在互联网内部是以 二进制流 ,也就是010101…
这种格式进行转发的。服务端最终接收到的只是一堆 二进制流 数据,并不清楚其具体代表的是什么含义,造成的后果也就如下图所示:
为了让服务端与客户端之间能够互相理解,需要先制定一套规范。客户端按照这套规范对需要发送的数据进行格式化,同样服务端按照这套规范对数据进行解析。比如下图中描述的就是一个最简单的规范格式:
根据上述规范,一个完整的网络请求操作包含以下几步:
客户端在发送之前,需要构造一个字节数组byte[2048],并使用前1024个byte保存账户”axing",将”123456”保存在后1024个byte中。
计算机网卡会将字节数组转换为二进制数据,并在互联网中进行传播。
服务端收到二进制数据之后,首先将其重新封装到byte数组中,然后从前1024个byte中取出账户信息,以及从后1024个byte中取出密码信息。
但是,实际项目中的网络请求远不止如此简单。我们经常需要在发送网络数据的同时,附带一些其它额外信息。比如请求日期Date、请求数据格式、语言类型、数据压缩格式、数据有效期等等。这就要求有一套定义更加完善,兼容性更高的规范来帮助我们实现更复杂的网络请求操作,而这套规范就是HTTP协议。
http协议格式简介
按照http协议收发的数据叫做http消息,
主要分为 请求消息 和 响应消息
不论是请求消息还是响应消息都具有严格的格式定义,更加详细的内容将会在后续实现OkHttp的文章中,循序渐进的向读者介绍。这节我们先简单了解下http消息主要由哪几部分组成,如下图所示:
可以看出,请求消息和响应消息都是由首行、消息头、消息体这3部分组成。但是两者也有一定的区别:
请求消息的首行叫做请求行,包含客户端发起请求的方法以及请求地址;
响应消息的首行叫做状态行,包含服务端的响应码与响应短语。
至于客户端具体可以使用哪种方法发起请求,以及服务端具体有哪些响应状态,会在后续实现文章详细介绍。
注意:实际上,不论是请求消息还是响应消息,在消息头和消息体之间都会有一个空行,用来代表消息头(Header)数据结束。
OkHttp与http之间的关系
在我介绍OkHttp时,我经常会将它称为
mini版浏览器,或者是 无UI版浏览器
因为OkHttp的工作机制与浏览器非常相似
同浏览器一样,OkHttp需要将用户的各种操作转化为相对应的http请求对象。比如下图中用户点击了"登录"操作,OkHttp会将其转化为图中右方的请求格式,并发送给服务端。
针对上述操作,一种简单的伪代码实现方式如下:
public void sendRequest() {OutputStream os = socket.getOutputStream();// 写入请求行os.write("POST ");os.write("/sample ");os.write("HTTP/1.1 \n");// 写入请求头os.write("Accept=*/*");...// 写入请求体os.write("account=axing\n");os.write("pwd=123456");
}
Header & Body
上述代码只是一种伪代码实现,如果实际实现也是直接使用OutputStream依次将所有数据进行写入操作,未免有些麻烦,这样的代码很不优雅。高级一点的工程师立马能想到应该在OutputStream之上封装一层实体类,用来代表请求头Headers和请求体Body。
实际上,在OkHttp中也正是使用了这种方式,Heads和Body如下所示:
/*** 请求头*/
public final class Headers {private final String[] namesAndValues;...
}/*** 请求体*/
public abstract class RequestBody {/** Returns the Content-Type header for this body. */public abstract @Nullable MediaType contentType();...public static RequestBody create(@Nullable MediaType contentType, String content) {Charset charset = Util.UTF_8;if (contentType != null) {charset = contentType.charset();if (charset == null) {charset = Util.UTF_8;contentType = MediaType.parse(contentType + "; charset=utf-8");}}byte[] bytes = content.getBytes(charset);return create(contentType, bytes);}
}
Request & Response
有了Header和Body之后,就可以创建出专门用来发送消息的请求类Request,如下所示:
这样框架使用者就可以很方便的使用Request类来存储一次网络请求的地址、请求方式、请求头、请求体等数据。
同样,对于响应消息也需要一个专门的封装类Response来表示,如下
请求发送和接收
不管是Request还是Response,都需要将数据提交给TCP协议层,并以流的形式在互联网中进行传播。在Java SDK中,有一个专门负责完成这一操作的类Socket,因此我们还需要手动调用Socket API实现网络通信。在OkHttp框架中,这部分操作被封装在HttpCodec类中,如下图所示
图中红框标记的finishRequest和openResponseBody,分别代表调用Socket发送请求数据,以及读取响应结果中的信息。
实际上,一次网络请求操作除了基本的通信需求之外,还需要考虑很多其它情况,比如缓存、代理、https支持等。本书在先实现网络通信的基础上,后续也会对这部分内容做详细封装介绍。
总结
本系列文章的内容是自己动手实现OkHttp框架,但实际最终目标是带领大家在实现过程中,对http协议(也有部分TCP协议)有一个完整深入的理解,这整个实现过程也可以看做是对http协议的二次封装。
如果你喜欢本文
长按二维码关注
OkHttp与HTTP协议相关推荐
- 创建Okhttp自定义Log
原文链接:创建OkHttp自定义Log 背景 本文重点讲解如何在使用OkHttp作为网络请求框架的前提下,如何自定义一个适合自己项目的Http Log,从而提升网络Api开发.调试效率. Http协议 ...
- Android Https相关完全解析 当OkHttp遇到Https
http://blog.csdn.net/lmj623565791/article/details/48129405: 本文出自:[张鸿洋的博客] 1. 概述 其实这篇文章理论上不限于okhttp去访 ...
- OkHttp相关知识(三)
相关面试题 1.OkHttp请求整体流程是怎么样? 答:Request->OkHttpClient->RealCall 同步 -> 在调用线程 执行五大拦截器 异步 -> 使用 ...
- Android:面试官死亡问答,如何优化一个网络请求?大牛多个网络优化方案帮你解决!
面试官:小萧啊,我好想你啊,你都好久没来找我面试了呀. 小萧:emmmmmmm,这不是怕被你打击吗. 面试官:ok,看来是有备而来,那么我们今天聊聊网络优化咋做吧. 小萧:我大意了,没有闪.老头子,你 ...
- 社交产品后端架构设计--转载
原文地址:http://www.uml.org.cn/zjjs/2015081311.asp 摘要:本篇文章会向读者展示几个架构设计的关键点,使一个社交应用能够成为真正的下一代社交产品.但这只是设计阶 ...
- Java EE 架构设计——基于okhttp3 的网络框架设计
转载请注明出处:http://blog.csdn.net/smartbetter/article/details/77893903 本篇文章带大家设计一套满意业务需求.代码健壮高效(高内聚低耦合)并且 ...
- Android入门知识全套笔记
安装apk: 开发完成之后,需要buildAPK,再次发送才能运行. adb install -r (apk完整路径) 安装在第三方app 系统级app需要把打包好的apk,浦西 卸载apk:adb ...
- 树莓派4B与Android之缘——Android应用MiniChat聊天软件
基本介绍和总体架构 一. 应用介绍 (一)基本介绍 MiniChat是一款聊天软件,你可以通过此软件进行聊天, 本应用集成了融云模块,从而实现集成通讯.主要功能是账号注册,登录,好友添加,好友间发送文 ...
- Glide核心设计二:缓存管理
原文链接:Glide核心设计二:缓存管理 引言 Glide作为一个优秀的图片加载框架,缓存管理是必不可少的一部分,这篇文章主要通过各个角度.从整体设计到代码实现,深入的分析Glide的缓存管理模块,力 ...
最新文章
- ASP.NET Core Web Razor Pages系列教程:使用ASP.NET Core创建Razor Pages Web应用程序
- Verilog篇(三)仿真原理
- GUI学习之十四——QAbstractSpinBox学习总结
- php 鼠标点击图片放大,css3如何实现鼠标放上图片放大?(附代码)
- 动态规划_leetcode322
- 2019年终总结-如果这是一场电影
- [PYTHON]python 基础笔记(1)
- face_recognition初始
- diamond简介和使用
- oppor829t如何刷机_科普OPPO R1 R829T的线刷教程及最简单的三星手机刷机教程
- win10录屏_一分钟教你学会两种电脑录屏的方法,以后别再说不知道了
- RAC环境报错ORA-00239: timeout waiting for control file enqueue排查
- 保镖机器人作文_暴力“保镖”作文800字
- 使用shopnc发送qq邮件遇到的坑
- matlab z rc电路,基于MATLAB模拟RC电路的暂态过程.pdf
- php跌涨算法,php砍价算法
- Android原生权限管理:AppOps
- 计算机内存4G,笔记本电脑4g内存和8g内存的区别
- Word制作毕业论文技巧实例--转载
- Word2010中自动尾注添加参考文献
热门文章
- 免费且不丢失数据的MBR转GPT软件!
- Netty网络框架学习笔记-16(心跳(heartbeat)服务源码分析)
- 前端实战小案例--canvas实战之FlappyBird小游戏
- 【MySQL】MySQL用 limit 为什么会影响性能?
- 详解数据分析中的行为分析
- 【C语言】a+aa+aaa+...+aa...a=?
- unirech阿里云国际版元宇宙解决方案
- 均方根与峭度系数_调节阀流量系数的影响因素及其工程应用调节阀流量系数的影响...
- 10 张有关程序员的趣图,图图戳心
- 时隔一年才发现嵌入式到底指的是什么