从HTTP原理到HTTP网络组件封装

HTTP所在的协议层

TCP:IP参考模型.jpg

HTTP工作过程

一次HTTP操作称为一个事务,其工作整个过程如下:

地址解析

如用客户端浏览器请求这个页面:http://localhost:8080/info,从中分解出协议名、主机名、端口、对象路径等部分,对于我们的这个地址,解析得到的结果如下:

协议名:http     主机名:localhost    端口:8080     对象路径:/info

在这一步,需要域名系统DNS解析域名localhost,得主机的IP地址。

封装HTTP请求数据包

Header

常见的媒体格式类型如下:

以application开头的媒体格式类型:

请求格式

  • Get

  • Post表单

  • Post上传
    上传时,传了一个参数key:name, value:Shawn,一个文件upload0.txt,一个data数据块。

把以上部分结合本机自己的信息,封装成一个HTTP请求数据包

封装成TCP包,建立TCP连接(TCP的三次握手)

 在HTTP工作开始之前,客户机(Web浏览器)首先要通过网络与服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能,才能进行更层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80。这里是8080端口

客户机发送请求命令

建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可内容。

服务器响应

服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。
实体消息是服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据

服务器关闭TCP连接

一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码
    Connection:keep-alive
   TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。

HTTP组件封装

封装的好处

  • 使用者只需要了解如何通过类的接口使用类,而不用关心类的内部数据结构和数据组织方法。
  • 高内聚,低耦合一直是我们所追求的,用好封装恰恰可以减少耦合
  • 只要对外接口不改变,可以任意修改内部实现,这个可以很好的应对变化
  • 类具有了简洁清晰的对外接口,降低了使用者的学习过程

封装的过程

大致分为以下三步:设计接口、填充实现、单元测试。

设计接口

这一步很重要,接口的好坏,直接决定了整个组件的好坏。
这个接口,需要有以下内容:
– 发起HTTP请求,具体是什么请求,需要自定义这个请求;
– 需要一个请求完成回来的回调;
– 回调中需要带一些内容。
这样在ZHHTTPClient类,只有一个类方法:

request是一个继承自NSObject的类,需要接收外部配置参数:

其中ZHHTTPUploadComponent, 是为上传准备的一个配置类,会接收上传文件的名称、路径、类型等:

这一个初始化方法是不够的,还有另外5个初始化方法,比如:

再加上response,回调block,HTTPMethod enum:

这些是全部的ZHHTTPClient Header中的内容。

填充实现

对主接口的实现如下:

先是根据设置的参数,对请求方法做了一个校准,然后再是根据是POST还是GET方法,再相应的私有方法。到现在为止还没有看出来,这个ZHHTTPClient内部是封装的哪种网络库,以后所有的更换网络库这种操作,是不需要动接口和这个实现函数的。
在具体的实现中,可以选择自己需要的网络框架,因为历史原因,追求稳定性,这里选择了ASI,代码如下:

ZHHTTPUploadComponent的实现就是对多个初始化方法指向一个全能初始化方法,把传进来的参数赋值到实例变量中。
ZHHTTPRequest实现在,会做默认值处理:

最后还有一个取MIME type的方法:

单元测试

正常POST:

文件上传:

文件下载:

直接填充body:

Get方法:

分类: 网络

发表评论

电子邮件地址不会被公开。 必填项已用*标注