[转载] HTTP 之 IOS一谈_weixin_30889885的博客-程序员秘密

技术标签: 操作系统  人工智能  移动开发  

HTTP在ios中虽然用的多,但对原理理解较少,这篇文章总结的挺好,留着学习。

HTTP属于老话题了,在项目中我们经常需要往服务端发POST或者GET请求,但是对于HTTP的了解不应只局限于此。千里之行,始于足下。越想走的远,基本原理就应该了解的透彻全面一些,仅仅停留在使用ASIHttpRequest或者AFNetWorking传个参数发个请求的程度上是不够的。这篇文章就是带你全方面回顾一下HTTP。
通过本文你能收获哪些内容:

·完整HTTP请求与响应包含的必要元素
·HTTP不同版本之间的差异
·HTTP、Socket、TCP的区别(易混)

一、HTTP协议

HTTP本质上是一种协议,全称是Hypertext Transfer Protocol,即超文本传输协议。从名字上可以看出该协议用于规定客户端与服务端之间的传输规则,所传输的内容不局限于文本(其实可以传输任意类型的数据)。


二、HTTP请求与响应的内容

当我们往服务端发送一条HTTP请求时都发送了哪些东西过去呢?

注:本文使用Paw来模拟发送HTTP请求,使用Charles抓包,Charles选中"Request"以及"Raw"选项就可以看到请求的全部内容
 

一个HTTP请求所必备的几大要素:请求行、请求头(headerField)、请求体(body);同理,响应也有状态行、响应头、实体内容。接下来我们逐个展开。

1、请求行

请求行包含请求方法(Method)、请求统一资源标识符(URI)、HTTP版本号,如图2.1第一行所示:

  • 请求方法就是我们所熟悉的POST、GET、HEAD、PUT等
  • URI就是URL中排除掉Host剩下的部分,也就是资源在服务器本地上的路径
  • HTTP版本号,目前主流的版本是1.1(1999年开始采用),最新的版本是2.0(2015年5月发布)。不同版本之间差异下面会再展开

2、请求头

请求头主要存放对客户端想给服务端的附加信息,下图框框的部分就是请求头:

HTTP请求在iOS中用NSURLRequestNSMutableRequest表示;HTTP响应用NSHTTPURLResponse表示。

  • Host: 目标服务器的网络地址
  • Accept: 让服务端知道客户端所能接收的数据类型,如text/html */*
  • Content-Type: body中的数据类型,如application/json; charset=UTF-8
  • Accept-Language: 客户端的语言环境,如zh-cn
  • Accept-Encoding: 客户端支持的数据压缩格式,如gzip
  • User-Agent: 客户端的软件环境,我们可以更改该字段为自己客户端的名字,比如QQ music v1.11,比如浏览器Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/600.8.9 (KHTML, like Gecko) Maxthon/4.5.2
  • Connection: keep-alive,该字段是从HTTP 1.1才开始有的,用来告诉服务端这是一个持久连接,“请服务端不要在发出响应后立即断开TCP连接”。关于该字段的更多解释将在后面的HTTP版本简介中展开。
  • Content-Length: body的长度,如果body为空则该字段值为0。该字段一般在POST请求中才会有。

    POST请求的body请求体也有可能是空的,因此POST中Content-Length也有可能为0

  • Cookie: 记录者用户信息的保存在本地的用户数据,如果有会被自动附上

    值得一提的是,在iOS中当你发送一个任意请求时,不管你愿不愿意,NSURLRequest都会自动帮你记录你所访问的URL上设置的cookie。在iOS中用NSHTTPCookieStorage表示,是一个单例。通过NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage]; for (NSHTTPCookie *cookie in [cookieJar cookies]) { NSLog(@"%@", cookie); }可以获取目前被自动保存的所有cookie。对cookie的操作感兴趣的请移步IOS中http请求使用cookie【http://rainbird.blog.51cto.com/211214/805173/】这篇文章。

以上就是我们日常开发中比较经常遇到的请求头,其实还有其他的field,但篇幅所限无法一一列出,想了解所有请求头请看这里请求头响应头列表http://tools.jb51.net/table/http_header。那在iOS中如何设置添加这些field呢?可以使用-[NSMutableURLRequest addValue: forHTTPHeaderField:]方法,获取当前请求已经设置的field可以用-[NSURLRequest allHTTPHeaderFields]。也就是我们可以通过以上接口定制我们所需要的请求头,但是有些field是不能改的,我们看一下iOSXcode中的描述:

 
从文档中我们可以看到,在iOS中不应当对 Authorization Connection Host WWW-Authenticate这几个header field做更改。

3、请求体

真正需要发给服务端的数据,在使用POST-multipart上传请求中请求体就是上传文件的二进制NSData类型数据;在GET请求中请求体为空;在普通的POST请求中请求体就是一些表单数据。在iOS中一般用NSURLRequestNSMutableURLRequestHTTPBody属性表示,添加body用-[NSMutableURLRequest setHTTPBody:]

4、响应状态行

状态行是服务端返回给客户端的状态信息,包含HTTP版本号、状态码、状态码对应的英文名称。
以下就是典型的正确状态行:
HTTP/1.1 200 OK
这个部分需要讲的是错误码。事实上HTTP请求错误码可以根据错误码从左往右第一个数字大致分为以下几类:

1XX:信息提示。不代表成功或者失败,表示临时响应,比如100表示继续,101表示切换协议
2XX: 成功
3XX: 重定向
4XX:客户端错误,很有可能是客户端发生问题,如亲切可爱的404表示未找到文件,说明你的URI是有问题的,服务器机子上该目录是没有该文件的;414URI太长
5XX: 服务器错误,比如504网关超时

错误码是不用去记的,出错了再查对应的错误码含义就行。但是知道上面的分类有助于第一时间做出大体的判断,起码你能清楚是服务端还是客户端的原因。

5、响应头与响应实体

这部分与请求部分差异不大,响应头的字field会有稍许不同,响应头中的header field同样移步请求头响应头列表http://tools.jb51.net/table/http_header。

三、HTTP版本简介

这里我把HTTP版本简单分为三类:1.1之前,1.1,2.0,针对这三类做个主要差异的介绍:

HTTP 1.1之前

  • 不支持持久连接。一旦服务器对客户端发出响应就立即断开TCP连接
  • 无请求头跟响应头
  • 客户端的前后请求是同步的。下一个请求必须等上一个请求从服务端拿到响应后才能发出,有点类似多线程的同步机制。

HTTP 1.1(主流版本)
与1.1之前的版本相比,做了以下性能上的提升

  • 增加请求头跟响应头
  • 支持持久连接。客户端通过请求头中指定Connectionkeep-alive告知服务端不要在完成响应后立即释放连接。HTTP是基于TCP的,在HTTP 1.1中一次TCP连接可以处理多次HTTP请求
  • 客户端不同请求之间是异步的。下一个请求不必等到上一个请求回来后再发出,而可以连续发出请求,有点类似多线程的异步处理。

HTTP 2.0
本着向下兼容的原则,1.1版本有的特性2.0都具备,也使用相同的API。但是2.0将只用于https网址。由于2.0的普及还需要比较长的一段时间,这里不展开,更多新特性请参考这篇文章http://www.uiseo.cn/http。

我们重点关注一下当前1.1版本所做几点改变。支持持久连接有什么好处呢?HTTP是基于TCP连接的,如果连接被频繁地启动然后断开就会花费很多资源在TCP三次握手以及四次挥手上,效率低下。以请求一个网页为例,我们知道,一个html网页上的图片资源并不是直接嵌入在网页上,而只是提供url,图片仍需要额外发HTTP 请求去下载。一个网页从请求到最终加载到本地往往需要经过过个HTTP请求。在1.1版本之前请求一个网页就需要发生多次"握手-挥手"的过程,每次连接之间相互独立;而1.1及之后的版本最少只需要一次就够。
再来就是请求异步,其好处参考多线程异步处理,在此不展开。

四、HTTP、Socket、TCP的区别

这三个概念经常被谈到,也是比较容易被混掉的概念。在回顾之前我们先看一下这三者在TCP/IP协议族中的位置关系:

HTTP是应用层的协议,更靠近用户端;TCP是传输层的协议;而socket是从传输层上抽象出来的一个抽象层,本质是接口。所以本质上三种还是很好区分的。尽管如此,有时候你可能会懵了,HTTP连接、TCP连接、socket连接有什么区别?好吧,如果上面的图解释的还是不够清楚的话,我们继续往下看。
 

1、TCP连接与HTTP连接的区别

上文提过,HTTP是基于TCP的,客户端往服务端发送一个HTTP请求时第一步就是要建立与服务端的TCP连接,也就是先三次握手,“你好,你好,你好”。从HTTP 1.1开始支持持久连接,也就是一次TCP连接可以发送多次的HTTP请求。
小总结:HTTP基于TCP

2、TCP连接与Socket连接的区别

在图4.1中我们提到,socket层只是在TCP/UDP传输层上做的一个抽象接口层,因此一个socket连接可以基于连接,也有可能基于UDP。基于TCP协议的socket连接同样需要通过三次握手建立连接,是可靠的;基于UDP协议的socket连接不需要建立连接的过程,不过对方能不能收到都会发送过去,是不可靠的,大多数的即时通讯IM都是后者。
小总结:Socket也基于TCP

3、HTTP连接与Socket连接的区别

区分这两个概念是比较有意义的,毕竟TCP看不见摸不着,HTTP与Socket是实实在在能用到的。

  • HTTP是短连接,Socket(基于TCP协议的)是长连接。尽管HTTP1.1开始支持持久连接,但仍无法保证始终连接。而Socket连接一旦建立TCP三次握手,除非一方主动断开,否则连接状态一直保持。
  • HTTP连接服务端无法主动发消息,Socket连接双方请求的发送先后限制。这点就比较重要了,因为它将决定二者分别适合应用在什么场景下。HTTP采用“请求-响应”机制,在客户端还没发送消息给服务端前,服务端无法推送消息给客户端。必须满足客户端发送消息在前,服务端回复在后。Socket连接双方类似peer2peer的关系,一方随时可以向另一方喊话。

4、问题来了:什么时候该用HTTP,什么时候该用socket

这个问题的提出是很自然而然的。当你接到一个与另一方的网络通讯需求,自然会考虑用HTTP还是用Socket。

  • 用HTTP的情况:双方不需要时刻保持连接在线,比如客户端资源的获取、文件上传等
  • 用Socket的情况:大部分即时通讯应用(QQ、微信)、聊天室、苹果APNs等

在iOS中,发HTTP请求一般用原生的NSURLConnectionNSURLSession或者开源的AFNetWorking(推荐)ASIHttpRequest(已停止更新)。连接Socket连接我用的比较多是robbiehanson大神的CocoaAsyncSocket 【https://github.com/robbiehanson/CocoaAsyncSocket】 (XMPPFramework也是出自他手)。

转载于:https://www.cnblogs.com/zhaoyunboy/p/http-in-ios.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30889885/article/details/95449912

智能推荐

石河子大学计算机专业录取分数线,石河子大学2018年各省及各专业录取分数线及最低录投档线【理科 文科】..._爱吃香菜的卷毛的博客-程序员秘密

人生就像攀岩,其实高考,只是我们奋力翻过的第一座山。等翻上山顶,你会发现,山的那边依旧有无数座山,等着你继续攀!2019年高考氛围越来越石河子大学浓,很多小伙伴关注石河子大学全国各省最低录取分数线,石河子大学最低投档线的相关信息。本文高考助手网小编整理了石河子大学录取分数线的相关信息,希望对于参加2019年的高考填报志愿其参考左右。奋斗在高考一线,埋头在书本之间,金榜题名只在弹指之间,愿你马到成功...

c语言编译器turbo,C语言编译器TurboC使用技巧解析_孙柔嘉的博客-程序员秘密

C语言编译器TurboC是为了照顾大量不熟悉DOS环境的初学者使用的软件,我们可以使用C语言编译器TurboC在Windows环境下安装和使用中文TurboC/C++3.0,完善Windows和中文DOS的运行环境。那么下面是C语言编译器TurboC使用教程一、为了照顾大量不熟悉DOS环境软件操作的初学者,您可以方便地安装TurboC/C++v3.0,在Windows环境下,的安装解析二、C语言编...

UILabel  设置渐变颜色字体_HW的技术博客的博客-程序员秘密

/*设置需要UILabel的字体、文本内容与颜色数组后,调用setGradientLabel方法即可显示*/GradientLabel.h#import @interface GradientLabel :[email protected] (nonatomic,strong) NSArray * colors;//字体渐变颜色数组(

LDA-math-认识Beta/Dirichlet分布_lda 撒旦的游戏_绝对不要看眼睛里的郁金香的博客-程序员秘密

2. 认识Beta/Dirichlet分布2.1 魔鬼的游戏—认识Beta 分布统计学就是猜测上帝的游戏,当然我们不总是有机会猜测上帝,运气不好的时候就得揣度魔鬼的心思。有一天你被魔鬼撒旦抓走了,撒旦说:“你们人类很聪明,而我是很仁慈的,和你玩一个游戏,赢了就可以走,否则把灵魂出卖给我。游戏的规则很简单,我有一个魔盒,上面有一个按钮,你每按一下按钮,就均匀的输出一个[0,1]之间的随机

用奶茶来聊聊数据分析原理。_IT农民工1的博客-程序员秘密

前一阵“秋天的第一杯奶茶”的梗刚刷爆我的朋友圈,这两天又开始了“冬天的第一杯奶茶”。从什么时候开始,连“奶茶自由”都成了人们的理想生活方式之一本来以为这件事情跟我没什么关系,但是那天我...

文件读写:fwrite与fprintf的区别(即二进制方式和文本方式的区别)_fwrite保存文本格式_guanyasu的博客-程序员秘密

C语言把文件看作一个字符(字节)的序列,即由一个一个字符(字节)的数据顺序组成。根据数据的组织形式,可分为ASCII文件和二进制文件。ASCII文件又称为文本(text)文件,它的每个字节放一个ASCII代码,代表一个字符。二进制文件是把内存中的数据按其在内在中的存储形式原样输出到磁盘上存放。fprintf(fp, "%d", buffer); 是将格式化的数据写入文件fprintf(

随便推点

linuxC--makefile使用变量_HHHU丶的博客-程序员秘密

使用变量定义变量的一般形式:变量名 赋值符 变量值变量名:由字母、数字和下划线组成赋值符:主要有=、:=、+=、?= 不同的赋值符有不同的意义变量值:文本字符串在含有变量的 makefile 中,make 执行是吧变量名出现的地方用对应的变量值来替换。makefile中的变量类型类似于C语言中的宏。makefile中的变量是区分大小写的,也就是说比那辆"varl" 和 “Varl” ...

vscode使用ssh远程连接失败(及其他问题合集)_与终端pty主机进程的连接没有响应_吨吨不打野的博客-程序员秘密

1. 常见解决方案2. 自己看日志找适合自己的解决方案看自己的输出信息,确定远程log文件的位置。使用xshell或者mobaxterm等远程连接工具,去查看上面这个日志文件,例如:vim /home/user/.vscode-server/.dfd34e8260c270da74b5c2d86d61aee4b6d56977.log找到其中的报错信息,例如我的是[15:13:51] [Error: Could not find pty on pty host, at C._throwI

21个故事让你成熟_weixin_34218890的博客-程序员秘密

1.甲去买烟,烟29元,但他没火柴,跟店员说:“顺便送一盒火柴吧。”店员没给。乙去买烟,烟29元,他也没火柴,跟店员说:“便宜一毛吧。”最后,他用这一毛买一盒火柴。这是最简单的心理边际效应。第一种:店主认为自己在一个商品上赚钱了,另外一个没赚钱。赚钱感觉指数为1。第二种:店主认为两个商品都赚钱了,赚钱指数为2。当然心理倾向第二种了。同样,这种心理还表现在买一送一...

mybatis 配置日志信息_祝志文--Alan的博客-程序员秘密

有很多的日志框架,我这以比较常用的Log4j为例设置日志的好处:可以清晰显示运行过程,方便理解mybatis执行过程 如果不指定具体的日志,Mybatis就会根据以下顺序 寻找日志 SLF4J →Apache Commons Logging →Log4j 2 → Log4j →JDK logging1.Log4j: 导入log4j.jar (mybatis.zip中lib中包含此jar)2.开启日志,conf.xml <settings> <!-- 开启日志,并指定使用的

深度学习 tf和np的float32和float64为什么不能通用_小鹏AI的博客-程序员秘密

标量和张量的区别标量比较就是比较标量的本事而张量的比较是比较矩阵,我们不能确定矩阵中所有的元素的长度都是一样的如果在进行比较的时候假设矩阵A和矩阵B比较矩阵A是float32的矩阵B是float64的如果两者要进行相加的时候,需要将每一个张量中的元素靠近另一个张量但是矩阵的元素过多,不能很好的达到统一因此张量中的类型需要相同...

微信--下载amr转mp3_微信amr转mp3_hijiang1的博客-程序员秘密

写得不错:http://www.cnblogs.com/zhongxia/p/5917163.html微信的录音文件上传到微信服务器上,只能保存三天。 因此需要做一个转存到自己服务器,或者七牛云的操作。转存到自己服务器调用微信JSSDK API 录音, 录音结束,上传到微信服务器,获取录音文件的 media_id根据 media_id 下载录音文件(amr)

推荐文章

热门文章

相关标签