OkHttp,从名字也能感觉到这套框架似乎与http协议有着千丝万缕的关系。事实上也确实如此,OkHttp所做的各种操作都是建立在http协议基础之上的。因此在理解并自己手写OkHttp之前,首先需要了解什么是http协议,以及http协议具体有哪些规则(或者说是格式)

为什么需要http协议

一般情况下,网络数据由客户端向服务端发送,数据进入互联网之后,是以二进制流(Stream)的形式进行传播,过程如下图所示:

客户端浏览器访问网页 “www.sample.com” 并进行登录操作,需要向服务端发送用户名与密码;然后服务端接收到客户端的请求之后,对数据进行封装、解析并返回响应结果。

但是正如图中所示,客户端发送的数据在互联网内部是以 二进制流 ,也就是010101… 这种格式进行转发的。服务端最终接收到的只是一堆 二进制流 数据,并不清楚其具体代表的是什么含义,造成的后果也就如下图所示:

为了让服务端与客户端之间能够互相理解,需要先制定一套规范。客户端按照这套规范对需要发送的数据进行格式化,同样服务端按照这套规范对数据进行解析。比如下图中描述的就是一个最简单的规范格式:

根据上述规范,一个完整的网络请求操作包含以下几步:

  1. 客户端在发送之前,需要构造一个字节数组byte[2048],并使用前1024个byte保存账户”axing",将”123456”保存在后1024个byte中。

  2. 计算机网卡会将字节数组转换为二进制数据,并在互联网中进行传播。

  3. 服务端收到二进制数据之后,首先将其重新封装到byte数组中,然后从前1024个byte中取出账户信息,以及从后1024个byte中取出密码信息。

但是,实际项目中的网络请求远不止如此简单。我们经常需要在发送网络数据的同时,附带一些其它额外信息。比如请求日期Date请求数据格式语言类型数据压缩格式数据有效期等等。这就要求有一套定义更加完善,兼容性更高的规范来帮助我们实现更复杂的网络请求操作,而这套规范就是HTTP协议。

http协议格式简介

按照http协议收发的数据叫做http消息,

主要分为 请求消息 和 响应消息

不论是请求消息还是响应消息都具有严格的格式定义,更加详细的内容将会在后续实现OkHttp的文章中,循序渐进的向读者介绍。这节我们先简单了解下http消息主要由哪几部分组成,如下图所示:

可以看出,请求消息和响应消息都是由首行消息头消息体这3部分组成。但是两者也有一定的区别:

  1. 请求消息的首行叫做请求行,包含客户端发起请求的方法以及请求地址;

  2. 响应消息的首行叫做状态行,包含服务端的响应码与响应短语。

至于客户端具体可以使用哪种方法发起请求,以及服务端具体有哪些响应状态,会在后续实现文章详细介绍。

注意:实际上,不论是请求消息还是响应消息,在消息头和消息体之间都会有一个空行,用来代表消息头(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协议相关推荐

  1. 创建Okhttp自定义Log

    原文链接:创建OkHttp自定义Log 背景 本文重点讲解如何在使用OkHttp作为网络请求框架的前提下,如何自定义一个适合自己项目的Http Log,从而提升网络Api开发.调试效率. Http协议 ...

  2. Android Https相关完全解析 当OkHttp遇到Https

    http://blog.csdn.net/lmj623565791/article/details/48129405: 本文出自:[张鸿洋的博客] 1. 概述 其实这篇文章理论上不限于okhttp去访 ...

  3. OkHttp相关知识(三)

    相关面试题 1.OkHttp请求整体流程是怎么样? 答:Request->OkHttpClient->RealCall 同步 -> 在调用线程 执行五大拦截器 异步 -> 使用 ...

  4. Android:面试官死亡问答,如何优化一个网络请求?大牛多个网络优化方案帮你解决!

    面试官:小萧啊,我好想你啊,你都好久没来找我面试了呀. 小萧:emmmmmmm,这不是怕被你打击吗. 面试官:ok,看来是有备而来,那么我们今天聊聊网络优化咋做吧. 小萧:我大意了,没有闪.老头子,你 ...

  5. 社交产品后端架构设计--转载

    原文地址:http://www.uml.org.cn/zjjs/2015081311.asp 摘要:本篇文章会向读者展示几个架构设计的关键点,使一个社交应用能够成为真正的下一代社交产品.但这只是设计阶 ...

  6. Java EE 架构设计——基于okhttp3 的网络框架设计

    转载请注明出处:http://blog.csdn.net/smartbetter/article/details/77893903 本篇文章带大家设计一套满意业务需求.代码健壮高效(高内聚低耦合)并且 ...

  7. Android入门知识全套笔记

    安装apk: 开发完成之后,需要buildAPK,再次发送才能运行. adb install -r (apk完整路径) 安装在第三方app 系统级app需要把打包好的apk,浦西 卸载apk:adb ...

  8. 树莓派4B与Android之缘——Android应用MiniChat聊天软件

    基本介绍和总体架构 一. 应用介绍 (一)基本介绍 MiniChat是一款聊天软件,你可以通过此软件进行聊天, 本应用集成了融云模块,从而实现集成通讯.主要功能是账号注册,登录,好友添加,好友间发送文 ...

  9. Glide核心设计二:缓存管理

    原文链接:Glide核心设计二:缓存管理 引言 Glide作为一个优秀的图片加载框架,缓存管理是必不可少的一部分,这篇文章主要通过各个角度.从整体设计到代码实现,深入的分析Glide的缓存管理模块,力 ...

最新文章

  1. ASP.NET Core Web Razor Pages系列教程:使用ASP.NET Core创建Razor Pages Web应用程序
  2. Verilog篇(三)仿真原理
  3. GUI学习之十四——QAbstractSpinBox学习总结
  4. php 鼠标点击图片放大,css3如何实现鼠标放上图片放大?(附代码)
  5. 动态规划_leetcode322
  6. 2019年终总结-如果这是一场电影
  7. [PYTHON]python 基础笔记(1)
  8. face_recognition初始
  9. diamond简介和使用
  10. oppor829t如何刷机_科普OPPO R1 R829T的线刷教程及最简单的三星手机刷机教程
  11. win10录屏_一分钟教你学会两种电脑录屏的方法,以后别再说不知道了
  12. RAC环境报错ORA-00239: timeout waiting for control file enqueue排查
  13. 保镖机器人作文_暴力“保镖”作文800字
  14. 使用shopnc发送qq邮件遇到的坑
  15. matlab z rc电路,基于MATLAB模拟RC电路的暂态过程.pdf
  16. php跌涨算法,php砍价算法
  17. Android原生权限管理:AppOps
  18. 计算机内存4G,笔记本电脑4g内存和8g内存的区别
  19. Word制作毕业论文技巧实例--转载
  20. Word2010中自动尾注添加参考文献

热门文章

  1. 免费且不丢失数据的MBR转GPT软件!
  2. Netty网络框架学习笔记-16(心跳(heartbeat)服务源码分析)
  3. 前端实战小案例--canvas实战之FlappyBird小游戏
  4. 【MySQL】MySQL用 limit 为什么会影响性能?
  5. 详解数据分析中的行为分析
  6. 【C语言】a+aa+aaa+...+aa...a=?
  7. unirech阿里云国际版元宇宙解决方案
  8. 均方根与峭度系数_调节阀流量系数的影响因素及其工程应用调节阀流量系数的影响...
  9. 10 张有关程序员的趣图,图图戳心
  10. 时隔一年才发现嵌入式到底指的是什么