1.前言

     ASIHttprequest 是基于CFNetwork的,由于CFNetwork是比较底层的http库,功能比较少,因此,在ASIHttprequest中实现了http协议中比较多的功能,包括代理、gzip、认证、缓存等等。目前,虽然ASIHTTPRequest已经不如前两年那么流行,但是分析一下其代码,对掌握CFNetwork库和HTTP协议还是有好处的,本文将简单分析一下ASIHTTPRequest中几个主要函数的流程。
 

2.处理HTTP Request的主要函数

ASIHTTPRequest::main流程如下(只列举了主要工作):

{
     (1)若允许后台运行,则调用beginBackgroundTaskWithExpirationHandler允许程序后台运行十分钟
     (2) 调用buildPostBody函数构造post的body部分,该函数有两个,一个是基类中的,主要负责压缩body数据,另一个是派生类ASIFormDataRequest中,分别针对post表单和post文件的方式,分别设置content-type为application/x-www-form-urlencoded和multipart/form-data。
     (3)根据url和请求的方法来创建CFHTTPMessageRef对象。
     (4)调用buildRequestHeaders函数来构造header部分,这里只是简单的将各个header字段放到一个NSDictionary变量中。
     (5)如果设置了缓存,并且允许从缓存取数据,则从缓存中读取数据,然后返回。
     (6)调用applyAuthorizationHeader向header字典中添加HTTP认证相关的字段。
     (7)调用CFHTTPMessageSetHeaderFieldValue来将header数据添加到CFHTTPMessageRef对象中。
     (8)调用configureProxies来配置代理。
     (9)调用startRequest来发送请求。
}
 

ASIHTTPRequest::startRequest

{

(1)向主线程发送requestStarted消息

(2)如果存在body,且需要post本地文件,则将本地文件读到postBodyReadStream对象中。然后调用CFReadStreamCreateForStreamedHTTPRequest函数,传入之前创建的CFHTTPMessageRef对象和postBodyReadStream对象,来创建一个用来读取response 的CFReadStream对象。

如果是post数据,则先根据shouldCompressRequestBody的值来判断是否要压缩,然后根据postBody的数据来创建一个NSInputStream对象,并赋给postBodyReadStream对象,然后调用CFReadStreamCreateForStreamedHTTPRequest,传入之前的header和stream对象,来创建NSReadStream对象。

如果不存在body,则直接通过CFReadStreamCreateForHTTPRequest函数来创建NSReadStream对象。

(3)针对https的情况,调用CFReadStreamSetProperty进行设置

(4)如果请求中设置了代理,则调用CFReadStreamSetProperty对stream进行代理相关的设置

(5)处理http持久连接相关的设置

(6)调用scheduleInRunLoop,将readStream对象放入runloop中

(7)调用CFReadStreamSetClient函数来将readStream关联到一个回调函数ReadStreamClientCallBack中,并使用CFReadStreamOpen打开readStream对象

(8)调用进度通知相关的函数

(9)创建一个计时器,用来调用updateStatus函数来更新进度,并将计时器放入当前runloop。

}

3.处理HTTP Response的主要函数

ASIHTTPRequest::handleNetworkEvent (该函数用来处理回调事件)

{

(1)当收到kCFStreamEventHasBytesAvailable 事件时 ,调用handleBytesAvailable(此时表示下层已经读到了response里的数据,这数据可能包含全部的header也可能header尚未读完)

(2)kCFStreamEventEndEncountered,调用handleStreamComplete,此时表示全部的数据包括header和body都已经读完,而且对应chunked数据,底层也已经将其合并完。

(3)kCFStreamEventErrorOccurred事件,调用handleStreamError处理错误

}

ASIHTTPRequest::handleBytesAvailable

{

(1)如果responseHeader对象尚未赋值,则调用readResponseHeaders读取header

(2)申请一块buffer,读取readStream对象里面的数据,此时如果能读到数据,则表示header已经读完了,当前读到的是body里面数据(因为header不是用read方法读的),如果读不到数据,则表示还没有收到body,则返回。

(3)读取到数据之后,如果header里面显示数据是压缩过的,则进行解压缩

(4)解压出数据之后有三种处理方式:

如果用户设置了didReceiveDataSelector或者dataReceivedBlock,这就表示用户希望自己处理每次得到的data,则向主线程发送passOnReceivedData消息。

如果用户在request中设置了下载路径,则将数据写到文件中

如果以上都不满足,则将数据append到rawResponseData中。

}

ASIHTTPRequest::readResponseHeaders

{

(1)使用CFReadStreamCopyProperty从readStream对象中读取header,创建一个CFHTTPMessageRef对象,并且使用CFHTTPMessageIsHeaderComplete检查该对象,判断header是否已经读完,若没有读完,则销毁该对象并返回

(2) 使用CFHTTPMessageCopyAllHeaderFields从CFHTTPMessageRef读出header到一个dictionary中

(3)如果有缓存,且允许读取缓存,则从缓存中读取header并返回。

(4)根据header中的状态码来判断是否需要进行http认证,如果需要则处理认证相关的工作

(5) 从header中content-type,用于对body进行解码,如没有该字段,则使用默认的解码方式对content进行解码

(6)处理cookie相关的工作

(7)如果不需要重定向,则从header中读取content-length,然后根据length做相关处理

(8)处理keepalive相关的工作

(9)最后向主线程发送requestReceivedResponseHeaders通知

}

ASIHTTPRequest::handleStreamComplete

{

该函数做的事情比较简单,主要就是设置各种下载结束的标志、设置读取到的文件大小并发送通知消息、移动下载的临时文件、保存cache等等。

}

 

ASIHTTPRequest源码简单分析的更多相关文章

  1. FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  2. FFmpeg源码简单分析:libswscale的sws_scale()

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  3. Django-session中间件源码简单分析

    Django-session中间件源码简单分析 settings里有关中间件的配置 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddlew ...

  4. FFmpeg源码简单分析:结构体成员管理系统-AVOption

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  5. negroni-gzip源码简单分析解读

    negroni-gzip源码简单分析解读 这是一个为Negroni设计的gzip压缩处理中间件,需要用到已有的compress中的gzip,阅读了不长的源码之后,总结了一些关键要点和注意点. 检查是否 ...

  6. FFmpeg的HEVC解码器源码简单分析:概述

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  7. FFmpeg的HEVC解码器源码简单分析:解码器主干部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  8. urllib源码简单分析

    对下面这段代码做分析 import urllib params = urllib.urlencode({'wd': 'python'}) f = urllib.urlopen("http:/ ...

  9. CardboardSDK-iOS 源码简单分析

    该项目地址: 地址 克隆地址为 https://github.com/rsanchezsaez/CardboardSDK-iOS.git 目前如果想在iOS设备上实现双目VR的功能,Google 已经 ...

随机推荐

  1. 解决 MYSQL CPU 占用 100% 的经验总结

    朋友主机(Windows 2003 + IIS + PHP + MYSQL )近来 MySQL 服务进程 (mysqld-nt.exe) CPU 占用率总为 100% 高居不下.此主机有10个左右的 ...

  2. Carve ifc failed

    Detected IFC version: IFC2X3 Warning: Sweeper::createTriangulated3DFace, carve::triangulate::incorpo ...

  3. 代理IP爬取和验证(快代理&西刺代理)

    前言 仅仅伪装网页agent是不够的,你还需要一点新东西 今天主要讲解两个比较知名的国内免费IP代理网站:西刺代理&快代理,我们主要的目标是爬取其免费的高匿代理,这些IP有两大特点:免费,不稳 ...

  4. (四)UML之顺序图(时序图)

    一.概念 顺序图是交互图的一种形式,它显示对象沿生命线发展,对象之间随时间的交互表示为从源生命线指向目标生命线的消息.顺序图能很好地显示那些对象与其它那些对象通信,什么消息触发了这些通信,顺序图不能很 ...

  5. Tensorflow 2.0 datasets数据加载

    导入包 import tensorflow as tf from tensorflow import keras 加载数据 tensorflow可以调用keras自带的datasets,很方便,就是有 ...

  6. java 画图 Graphics 文字自动换行

    /** * 文字超出限定长度自动换行 * * @param g 画布 * @param font 字体样式 * @param text 文字 * @param widthLength 最大长度 (多少 ...

  7. NLog文章系列—系列文章目录以及简要介绍

    参考文章:http://www.cnblogs.com/dflying/archive/2006/12/04/581750.aspx

  8. Memcached的安装与常用命令

    一.概述 MSM:Memcached-Session-ManagerMemcached是一款高性能.分布式的内存对象缓存系统 二.安装Memcached 在安装Memcached之前,我们需要先安装上 ...

  9. 20175316 盛茂淞 2018-2019-2 《Java程序设计》实验四 《Android程序设计》 实验报告

    实验四 Android程序设计 实验要求 参考Android开发简易教程 完成云班课中的检查点,也可以先完成实验报告,直接提交.注意不能只有截图,要有知识点,原理,遇到的问题和解决过程等说明.实验报告 ...

  10. [转帖]新手必读,16个概念入门 Kubernetes

    新手必读,16个概念入门 Kubernetes https://www.kubernetes.org.cn/5906.html 2019-09-29 22:13 中文社区 分类:Kubernetes教 ...