YGben

熟悉又陌生的HTTP协议


关于HTTP协议的基本点。旧物重拾,总觉陌生又熟悉。HTTP经常用,但是却不一定知道的多少。

上野宣著

  • HTTP无状态
  • HTTP基于TCP
  • 长连接

无状态

HTTP自身是不保存请求和响应之间的通信状态的,每次使用HTTP,都是新的请求发送对应新的响应产生。

诸如购物网站需要保存用户状态的,需要根据之前的状态进行本次的请求处理,由于HTTP是无状态的,跳转新页面,只能重新登陆或者在请求报文中附加参数来管理状态。

这个时候就引入了 Cookie技术,Cookie由服务器生产,保存在客户端,会自动在请求中加入Cookie发送出去,以此种方式服务器就判别到底是A还是B发送过来的请求。

1
2
3
4
5
6
7
8
participant Web Client
participant Web Server
Web Client->>Web Server: Request
Web Server->>Web Client: Response + Set-Cookie
Web Client->>Web Server: Request + Cookie
Web Server->>Web Client: Response

Cookie 本身存在客户端中,这样会减少服务器的压力,但是用户一旦删除就需要重新获取,同样也是不安全的。那存在服务器端是不是更安全一些?

Session就出现了。Session存放在服务端,但是Session本身也无法判断请求来自哪个用户。

通常用Cookie管理Session,在Cookie中包含Session ID,这样通过Session ID 就判别是谁发来的请求。

为什么基于TCP

其实HTTP也可以基于其他传输层的协议,这里指通常我们平时用到的HTTP。

HTTP使用TCP而不是UDP的原因在于(打开一个)一个网页必须传送很多数据,而TCP协议提供传输控制,按顺序组织数据,和错误纠正。UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠性较差。

TCP是面向连接的,有比较高的可靠性,一些要求比较高的服务一般使用这个协议,如FTP、Telnet、SMTP、HTTP、POP3等,而 UDP是面向无连接的,使用这个协议的常见服务有DNS、SNMP、即时通讯、实时直播等。

长连接

HTTP1.0提出了持久连接(persistent connection),HTTP1.1 默认保持持久连接。这样的目的就是解决基于TCP三次握手的开销,复用TCP连接,持久连接就不必着急的断开。

Connection:keep-alive

短连接的时候就是一锤子买卖。TCP通过三次握手,建立“靠谱”的通道,然后HTTP传输数据,服务端发送完数据就关闭,客户端读数据时会返回EOF(-1),就知道数据已经接收完全了。就这样,循环往复,TCP不厌其烦的三次握手。

长连接完成一次HTTP后,服务端不关闭,那怎么知道数据传输完成?

当服务器一次性知道响应报文的大小,会通过 Content-Length 属性来返回。

Content-Length:47 // 截取www.baidu.com Repose 报文

当服务器非一次性返回报文的时候,比如动态页面,服务器也不知道内容大小。

Transfer-Encoding:chunked //截取www.meituan.com

分块传输(chunked),这时候就要根据chunked编码来判断,chunked编码的数据在最后有一个空chunked块,表明本次传输数据结束

chunked

数据以一系列分块的形式进行发送。 Content-Length 首部在这种情况下不被发送。在每一个分块的开头需要添加当前分块的长度,以十六进制的形式表示,后面紧跟着 ‘\r\n’ ,之后是分块本身,后面也是’\r\n’ 。终止块是一个常规的分块,不同之处在于其长度为0。终止块后面是一个挂载(trailer),由一系列(或者为空)的实体消息首部构成。

后记

HTTP是网络应用层很重要的基石,CFNetwork文档有如下表格,说到底HTTP只是一个协议,一个B/S约定的规则。因为还没有相关基于socket网络编程的经验,只是运用网络API,还在NSURL晃荡。很多东西不是第一手接触到,但是读读开篇那本书,还是有收获的。
Web Kit |
:—-:|
NSURL |
CFNetwork |
BSD sockets |

参考

感谢
阮一峰 HTTP 协议入门
RFC Hypertext Transfer Protocol – HTTP/1.1
HTTP的长连接和短连接