HTTP2--转https://www.cnblogs.com/insane-Mr-Li/category/1216836.html
http协议进阶(二)URL与资源
一、URL的语法
URL是互联网资源的标准化名称
URL提供了一种定位互联网上任意资源的手段,但这些资源要通过不同方案(协议:比如http、ftp、smtp)来访问,因此URL语法会略有差异
大部分URL都遵循通用的语法,而且不同URL方案风格和语法都有重叠
大多数URL协的语法都建立在下面9个部分构成的通用格式上:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
其中最重要的3个部分是:方案(scheme)、主机(host)和路径(path)
通用URL组件:
1、方案-使用什么协议
方案:实际上规定了如何访问指定资源的主要标识符,它告诉负责解析URL的应用程序应该是用什么协议
方案组件必须以一个字母符号开始,由第一个“:”符号将其与URL其余部分分隔开来。(方案名大小写不敏感)
2、主机与端口
想要在往上寻找到资源,应用程序需要知道哪台机器装载了资源,以及在机器的什么地方可以找到对目标资源进行访问的服务器,URL的主机和端口提供这2点信息
主机组件标识了往上能访问资源的宿主机器。可用主机名或者IP地址来表示主机名。比如下面2个URL就是指向同一个资源
主机名指向:http://joes-hardware.com:80/index.html
IP指向:161.58.228.45:80/index.html
端口组件标识了服务器正在监听的网络端口。对下层使用TCP协议的http协议来说,默认端口为80
3、用户名和密码
有些服务器都要求输入用户名和密码才允许用户访问数据,比如FTP(文件传输协议),如下面几个例子
ftp://ftp.prep.ai.mit.edu/pub/gnu
没有用户名和密码,只有标准的协议、主机和路径;如果某个应用程序使用的URL协议要求输入用户名密码,但用户没有提供,通常会插入一个默认的用户名和密码,比如FTP
ftp://anonymous@ftp://ftp.prep.ai.mit.edu/pub/gnu
指定了一个用户名anonymous,与主机组合在一起,看起来像一个email地址一样;字符“@”将用户名和密码组件与其他部分分隔开来
ftp://anonymous:my_password@ftp://ftp.prep.ai.mit.edu/pub/gnu
指定了用户名和密码,两者之间由字符“:”隔开
4、路径
路径说明了请求的资源位于服务器的什么地方,通常是一个分级的文件系统路径;比如:
http://joes-hardware.com:80/seasona/index-fall.html
这个URL中的资源路径就是seasona/index-fall.html,很像Unix文件系统中的文件系统路径
路径是服务器定位资源所需的信息,可以用“/”将http URL中的路径组件划分为一些路径段(path segment),每个路径段都有自己的参数字段
5、参数
对很多协议来说,只有简单的主机名和到达对象路径的是不够的,除了端口和用户名密码,还需要更多的内容才可以访问
有些负责解析URL的应用程序需要协议参数才能工作;否则服务器不会提供服务,或者提供错误的服务,比如
ftp协议有两种传输方式:二进制和文本。如果用文本形式传送二进制图片,结果很难预料有多糟糕
参数组件是URL中的名值队列表,由“/”将其与其他部分分隔开,比如
ftp://ftp.prep.ai.mit.edu/pub/gnu;type=d
参数为type=d,其中参数名为type,值为d
6、查询字符串
在我们发送请求时,很多的资源,比如数据库服务,都可以通过查询来缩小请求资源的类型范围,例如
http://www.joes-hardware.com/inventoty-check.cgi?itcm-12731
问号(?)右边的内容就是这个URL的查询组件。URL的查询组件和标识网关资源的URL路径组件一起被发送给网关资源。可以将网关当做访问其他应用程序的访问点
如下图:查询目的是检查清单中是否size为large、color为blue的条目
网关基本都是希望查询字符串以一系列“名/值”对的形式出现,名值对之间用“&”分隔
上面的例子,查询组件有2个名/值对:item=12731和color=blue
7、片段
有些资源类型,比如HTML,除了资源级意外,还可以进一步划分,比如一个带有章节的大型文本文档,资源的URL会指向整个文档,但理想情况,可以指向资源中的章节
为了方便引用,URL允许使用片段(frag)组件来表示资源内的一个片段,片段挂在URL右边,最前面有一个字符“#”,比如:
http://www.joes-hardware.comtools.html#drills
这个例子中,片段引用了joes-hardwareweb服务器上页面/tools.html中的一个部分,这部分名字叫drills
服务器处理的是整个对象,URL片段仅由客户端使用并展示
二、URL快捷方式
web可以理解并使用URL的快捷方式,比如缩略,自动扩展(用户输入关键部分,浏览器负责填充)
1、相对URL
URL有2种方式:绝对的和相对的。目前为止,我们使用的URL基本都是绝对的,它包含了访问资源所需的全部信息
相对URL是不完整的,要从相对URL中获取访问资源的全部信息,就必须相对于另一个基础(base)的URL进行解析
相对URL是URL的一种便捷缩略记法,下面是一个嵌入了相对URL的HTML文档实例
<html>
<head><title>joe's tools</title></head>
<body>
<h1>tools page</h1>
<h2>hammers<h2>
<p>joe's hardware online has the largest selection of<a herp="./
hammers.html">hammers
<a/>on earth
</body>
</html>
上面的例子是资源http://www.joes-hardware.com/tools.html的HTML文档,在这个文档中包含了URL./hammers.html的超链接
虽然看起来不完整,但实际上是合法的相对URL,这个URL可以相对于它所在的文档中的URL对其进行解释
使用缩略形式的相对URL语法,写HTML时就可以省略URL中的方案、主机和其他一些组件,这些组件可以从所属资源的基础URL中推导出来,其他资源的URL也可以用这种缩略形式来表示
下图说明了如何从基础URL中推导出缺失的组件信息
相对URL只是URL的片段或一小部分,处理URL的应用程序需要在相对和决定URL之间进行转换
PS:相对URL为了保持一组资源(HTML页面)的便捷性提供了一种便捷方式,如果使用相对URL,可以在搬移一组文档时,仍保持链接的有效性;
因为相对URL是相对于新基础进行解释的,类似于在其他服务器提供镜像内容等功能
1.1 基础URL
基础URL是作为相对URL的参考点来使用的,可以来自以下不同的地方:
在资源中显式提供:有些资源会显式指定基础URL
比如:HTML文档中可能会包含一个定义了基础URL的HTML标记<BASE>,通过它来转换HTML文档中的所有相对URL
封装资源的基础URL:如果在一个没有显式指定基础URL的资源中发现一个相对URL,如上面的HTML文档所示,可将其所属资源的URL作为基础
没有基础URL:某些情况没有基础URL,一般意味着你有一个相对URL,但有时可能只是一个不完整或者损坏的URL
1.2 解析相对引用
解析:要将相对URL转换为一个决定URL,需要将相对URL和决定URL划分成组件段,这样,实际上只是在解析URL,但这种做法会将其划分为一个个组件,可以称之为解析/分解URL
将基础和相对URL划分成组件,可以下用下图的算法来完成转换
这个算法将一个相对URL转换成了其绝对模式,之后,就可以用其引用资源
2、自动扩展URL
很多浏览器会在用户提交URL/输入URL时尝试自动扩展URL,这样为用户提供便捷,用户不需要输入完整的URL,浏览器自动扩展
自动扩展特性有以下2种方式:
2.1 主机名扩展
只要有些小提示,浏览器就可以帮你将输入的主机名扩展为完整的主机名,比如:输入baidu,构建出www.baidu.com;弊端在于有时候会为其他http应用程序带来问题,比如代理,后面详细解释
2.2 历史扩展
将以前用户访问过的URL记录储存起来,当用户输入URL时将其与历史记录中的URL前缀进行匹配,并提供一些完整的选项供用户选择
PS:与代理一起使用时,URL自动扩展的行为可能有所不同,后面详细解释
三、URL字符集
URL是可移植的:它命名了互联网上所有的资源,需要通过各种不同协议来传输资源,资源在传输时采取了不同的机制,因此,信息的安全传输就很重要
安全传输意味着URL传输不能丢失信息,但有些协议,比如SMTP(简单邮件传输协议),传输方法就是剥去一些特点的字符
URL是可读的:因此,即使不可见、不可打印的字符能穿过邮件程序,从而成为可移植的,也不能在URL中使用
URL是完整的:有人希望URL中包含初通用的安全字母表之外的二进制数据或字符,因此需要一种转义机制,将不安全的字符编码为安全字符再传输
1、URL字符集
1.1 很多计算机应用程序使用的都是ASCII字符集,ASCII使用7位二进制码来表示大多数按键和少数不可控字符,其移植性也很好,但考虑到全球用户太多,以及有时候URL中会包含任意二进制数据
就需要将转义序列集成进来,通过转义序列将ASCII字符集的有限子集对任意字符值或数据进行编码,这样就实现了可移植和完整性
1.2 编码机制
为了避开安全字符集带来的限制,人们设计了“转义”表示法来表示不安全字符,其中包含一个百分号(%),后面跟2个表示字符ASCII码的十六进制数,下面是几个例子
1.3 字符限制
URL中,有几个字符被保留起来,有着特殊含义。有些字符不在定义的ASCII字符集中,还有些字符会和某些协议网关产生混淆,因此不赞成使用
四、常见协议
下面附录一个关于常用常见的协议列表
五、URL未来发展
URL可用来命名所有现存对象,其还提供一种可在各种协议间共享的统一命名机制,但并不完美;因为URL只表示实际地址,而不是准确的名字,意味着如果资源地址有变化,URL就无法对其进行定位
永久统一资源定位符(PURL),其本质是搜索资源过程中引入一个中间层,通过一个中间资源定位符(resource locator)服务器对资源的实际URL进行登记和追踪
客户端可以向定位符请求一个永久的URL,定位符可以以一个资源为响应,将客户端重定向到资源当前的URL去
http协议进阶(三)http报文
一、报文流
http报文是在http应用程序之间发送的数据块(也可称为数据包)、这些数据块以一些文本的元信息(meta-information)开头,描述了报文的内容及含义,后面跟着
可选的数据部分,这些报文在客户端、服务器和代理之间流动;常说的术语“流入”、“流出”、“上游”、“下游”就是描述报文方向的
1、报文流入源服务器
http使用术语流入(inbound)和流出(outbound)来描述事务处理的方向;报文流入源服务器,工作完成后,流回用户的Agent代理中,如下图
2、报文向下游流动
不管是请求还是响应报文,所有报文都会向下游流动,所有报文发送者都在接收者的上游,如下图
二、报文的组成
http报文是简单的格式化数据块,如下图
每条报文包含一个客户端请求或者服务端响应,由三部分组成:1)对报文进行描述的起始行;2)包含属性的首部(header)模块;3)可选的,包含数据的主体(body)部分
起始行和首部就是由行分隔的 ASCII文本。每行都以一个由2个字符组成的行终止序列作为结束,包括一个回车符(ASCII码13)和一个换行符(ASCII码10),这个行终止
序列可以写为CRLF。(稳健的应用程序也应该接受单个换行符作为行的终止)
实体或报文的主体是一个可选数据块,与起始行和首部不同的是,主体中可包含文本或二进制数据,也可以为空
如上图,Content-type行说明了主体是一个纯文本文档,Content-length说明了主体有19字节
1、报文的语法
所有的http报文都分为请求报文和响应报文,请求报文会向服务器发送一个请求动作,响应报文会将请求结果返回给客户端,其结构基本相同;下图显示了获取一张GIF图所需的请求和响应报文
这是请求报文的格式 这是响应报文的格式
<method> <request-URL> <version> <method> <status> <version>
<headers> <heraers>
<entity-body> <entity-body>
下面是对各部分的简述:
方法(method):客户端希望服务器对资源执行的动作,是一个单独的词,比如GET、HEAD、POST等
之前的博客http://www.cnblogs.com/imyalost/p/5630940.html中有简单介绍几种方法,不过后面会详细解释这些方法
请求URL(request-URL):命名了请求资源,或者URL路径组件的完整URL;如果直接与服务器进行对话,只要URL的路径是决定路径,通常不会出现问题(上一篇随笔有详细介绍URL......)
版本(version):报文所使用的http协议版本——HTTP/<major>.<minor>;其中主要版本号(major)和次要版本号(minor)都是整数,本篇后面详解
状态码(status-code):3位数字,描述请求过程中发生的情况,每个状态码第一位描述状态的一般类别(成功/错误),本篇后面解释http规范的状态码及其含义
之前的博客http://www.cnblogs.com/imyalost/p/5688169.html也有简单介绍
状态码还有一种可读版本,包含终止序列之前的版本;比如HTTP/1.1 200 NOT OK和HTTP/1.1 200 OK中原因短语不同,但同样被当做成功指示处理
首部(header):可以有0个或多个首部,每个首部包含一个名字,后面跟一个冒号,然后一个可选空格,接着一个值,最后是CRLF。首部由一个空行(CRLF)结束,表示首部列表的结束和实体主体的开始。
实体主体(entity-body):包含一个由任意数据组成的数据块。
2、起始行
所有http报文都以一个起始行作为开始;请求报文说明了要做什么,响应报文说明发生了什么
2.1 请求行
请求报文请求服务器对资源进行一些操作。请求报文起始行,称为请求行,包含一个方法和一个请求。
该方法描述了服务器应该执行哪些操作,请求URL描述了要对哪个资源执行这个方法,请求行中还包括http版本,告知服务器,客户端使用哪个版本http协议,由空格符分隔
上图中,请求方法为GET,请求URL为test/hi-there.txt,http版本为1.1。
2.2 响应行
响应报文承载了状态信息和操作产生的所有结果数据,将其返回给客户端。响应报文起始行,称为响应行,包含了使用的http版本,数字状态码,以及描述操作状态或文本形式的原因短语。
这些字段由空格符进行分隔,在上图中,http版本为1.0,状态码200(表示成功),原因短语为OK,表示文档被成功返回。
2.3 方法
请求的起始行以方法作为开始,方法用来告知服务器做什么。如上图,方法就是GET,下表列出一些现版本http有的一些方法
具体的方法介绍下面会介绍
2.4 状态码
状态码用来告诉客户端,发生了什么事;状态码位于响应的起始行中。状态码在每条响应报文的起始行中返回的,以一个数字和一个可读的状态组成;数字码便于程序进行差错处理,原因短语则便于理解
下面列出状态码的分类:
具体的方法介绍下面会介绍
2.5 原因短语
原因短语为状态码提供了文本形式的解释,和状态码成对出现,是状态码的可读版本,应用程序将其传给客户,说明在请求期间发生了什么;稍后会整理出一些状态码和其建议使用的一些原因短语
2.6 版本号
版本号会以http/x、y的形式出现在请求和响应报文的起始行中,为应用程序提供了一种将自己遵循的协议版本告知对方的方式
通信时最好使请求和响应的版本号保持一致,否则很容易造成误解,使程序无法识别
PS:版本号不会被当做分数处理,每个数字都是独立的,比如,HTTP/2.22版本高于HTTP/2.3
3、首部
http首部字段向请求和响应报文中添加一些附加信息;本质来讲,他们知识一些名/值对的列表。
3.1 首部分类
通用首部:即可出现在请求报文中,也可出现在响应报文中
请求首部:提供更多有关请求的信息
响应首部:提供更多有关响应的信息
实体首部:描述主体的长度和内容,或者资源本身
扩展首部:规范中没有定义的新首部
每个http首部都有一种简单的语法:名字后面是冒号(:),然后跟上可选的空格,再跟上字段值,最后以一个CRLF结束
3.2 首部延续行
将长的首部行分为多行可提高可读性,每行前面至少有一个空格或制表符(tab),例如
HTTP/1.1 200 OK
Conteng-Type: image/gif
Content-Length: 8572
Server: Test Server
Version 1.0
上面的例子,响应报文中包含一个Server首部,其值被划分为多个延续行,该首部完整值为Server: Test Server Version 1.0
4、实体的主体部分
http报文的第三部分为可选的实体主体部分,实体是主体的http报文的负荷,就是http要传输的内容,资源
http报文可承载很多类型的数字数据:图片、视频、HTML文档、软件应用程序、电子邮件等
三、方法
1、GET
GET是最常用的方法,通常用于请求服务器发送某个资源(资源是已被服务器识别或标识的)给客户端; 如下图
服务器在获取GET请求参数时用Request.QueryString,意思为获取地址栏中的参数,就是“?”后面的参数,如果是多个,就用&连起来
2、HEAD
HEAD和GET方法类似,但在响应中只返回首部,不返回实体的主体部分。使用HEAD方法,可以
*在不获取资源的情况下了解资源的实际情况(资源类型)
*通过查看状态码,确认资源是否存在(有效性)
*通过查看首部,测试资源是否被修改(如修改,资源修改时间等)
3、PUT
与GET相反,PUT方法会向服务器写入文档(有些系统会允许用户创建web界面,并用PUT方法直接将其安装到web服务器上)
PUT方法实际上就是让服务器用请求中包含的主体部分来创建一个由请求的URL命名的新文档;或者URL已存在的话,就用这个主体来替代它。
因为PUT允许用户对内容进行修改,所以现在很少用这个方法,如果使用了这个方法,都要求用户使用授权的密码登陆(后面会整理出来关于安全认证的相关内容)
4、POST
POST方法用来向服务器发送提交数据的请求,具体的内容这里就不赘述了,之前有写过关于这方面的随笔,里面介绍了post及它与get的区别等内容(http://www.cnblogs.com/imyalost/p/5630940.html)
5、TRACE
客户端发起一个请求时,请求可能要穿过防火墙、代理、网关或者其他应用程序,每个中间节点可能都会修改原始的http请求,TRACE允许客户端在最终把请求发给服务器时,查看它最终的样子
TRACE请求会在目的服务器端发起一个“回环”诊断。最后一站服务器会弹回一个TEACE响应,并在响应报文主体中携带原始请求报文,这样客户端就可以查看在所有中间节点上,原始报文是否被修改或毁坏
6、OPTIONS
请求web服务器告知其支持的各种功能;可以询问服务器支持哪些方法,或者对某些特殊资源支持哪些方法(有些服务器可能只支持对一些特殊类型的对象使用特定操作)
为客户端提供了一种手段:不用实际访问资源就可判定访问各种资源的最优方式
7、DELETE
请求服务器删除请求URL所指定的资源;但客户端应用程序不一定会执行删除操作,因为http协议规范允许服务器在不通知客户端的情况下撤销请求。如下图
8、扩展方法
http被设计成可扩展的,这样新特性就不会使老的版本失效。扩展方法指的是没在HTTP/1.1中规范定义的,服务器为它管理的资源实现一些HTTP服务,为开发者提供了一种扩展这些HTTP服务能力的手段
下表列出了一些常用的扩展方法:
上面例子中的方法便于用过http将web内容发布到web服务器上
不是所有的扩展都是在正式规范中定义的,因此,扩展方法秉持“对发送内容要求严格,对所接受的内容宽容点”来处理一般的HTTP扩展方法很重要
四、状态码
响应报文的返回状态码分为五类,之前的随笔进行了介绍,这里就当做是补充吧
状态码是一种理解事务处理结果的便捷方式;下面列出一些常见的原因短语例子,都是目前最常用的HTTP/1.1规范推荐使用的
1、100~199——信息性状态码
100 Continue的目的是对这样的情况进行优化:http客户端应用程序有一个主体的实体部分要发送给服务器,但发送之前希望查看服务器是否会接受这个实体
1.1 客户端与100 Continue
如果客户端向服务器发送一个实体,并愿意在发送前等待100 Continue响应,那么客户端就要发送一个携带了值为100 Continue的EXpect请求首部;如果客户端没发送实体,
就不应发送100 Continue Expect首部。因此客户端只有在避免向服务器发送一个服务器无法处理或使用的较大的实体时,才应使用100 Continue
解决办法:发送了100 Continue的Expect首部值的客户端不应一直等待响应,超过一定时间(可设置),自动将实体发送出去;同时做好应对非预期100 Continue响应的准备
1.2 服务器与100 Continue
如果服务器收到带有值为100 Continue的Expect首部请求,它会用100 Continue或一条错误码来响应;服务器永远不应向没有发送100 Continue请求的客户端发送100 Continue状态码
如果服务器在发送100 Continue响应前收到部分或全部实体,说明客户端决定继续发送数据,此时,服务器不需要发送这个状态码,但读完请求,应继续返回一个最终状态码(跳过100 Continue状态)
如果服务器收到带有100 Continue的请求,且它决定在读完实体主体前结束请求,就不应仅仅发送一条响应并关闭连接,这样会影响客户端接收响应
1.3 代理与100 Continue
代理从客户端收到带有100 Continue期望的请求,有以下几种情况:
如果知道下游服务器是http/1.1兼容或不清楚下游服务器与哪一个版本兼容,应将Expect首部放在请求中向下转发
如果知道下游服务器只能与http/1.1以下的版本兼容,就应该以417 Expectation Failed错误进行响应
如果代理决定代表与http/1.1或之前的版本兼容的客户端,在其请求中放入Expect首部和100 Continue值,那么它不应将100 Continue转发给客户端
2、200~299——成功状态码
下面列车一些服务器用来表示成功的状态码,分别对应不同的请求
3、300~399——重定向状态码
告知客户端使用替代位置来访问它感兴趣的资源;或提供一个替代的响应而不是资源内容
或在资源已被移动情况下,发送一个重定向状态码和一个可选的Location首部告知客户端,资源已被移动,且在哪里可以找到寻找的资源,如下图:将请求重定向到新的位置
可通过某些重定向状态码对资源的应用程序本地副本与源服务器上的资源进行验证;比如http应用程序可以查看本地资源是否是最新的或者是否被修改过
总之,对那些包含了重定向状态码的非HEAD请求进行响应时,最好包含一个实体,其实体中包含描述信息和指向(多个)重定向URL的链接——如上图第一个响应报文
下表列出已定义的重定向状态码:
上面302、303于307状态码之间存在一些交叉,区别在于HTTP/1.0和HTTP/1.1对其的处理方式:
当HTTP/1.0发起一个POST请求,并在响应中收到302重定向状态码时,它会接受Location首部重定向的URL,并向那个URL发起一个GET请求
如果HTTP/1.0服务器收到来自HTTP/1.0客户端的POST请求之后,发出302状态码,服务器希望客户端能接受重定向URL并向重定向URL发一个GET请求
但是,HTTP/1.1规范使用303状态码来实现以上行为(服务器发送303状态码重定向客户端的POST请求,在其后面跟上一个GET请求)
为规避上述问题,HTTP/1.1规范:对于HTTP/1.1客户端,用307来取代302状态码进行重定向(保存302状态码,留待HTTP/1.0使用→→服务器遇到类似情况需要先检查客户端HTTP版本)
4、400~499——客户端错误状态码
有时候客户端会发送一些服务器无法处理的请求,比如格式错误的报文或者不存在的URL,服务器会返回给我状态码告诉我们它的反应
很多客户端错误都由浏览器处理,只有少量错误,比如404,会被用户看到;下表列出各种客户端错误状态码
5、500~599服务器错误状态码
有时客户端发起一个请求,但服务器由于本身缺陷或子元素出错时,会出现此类问题,服务器返回5XX代码来描述遇到的问题
下表列出一些已定义的服务器错误状态码
http协议进阶(四)报文首部
之前写的关于报文首部的传送门:
报文首部:http://www.cnblogs.com/imyalost/p/5708445.html
通用首部字段:http://www.cnblogs.com/imyalost/p/5717430.html
请求首部字段:http://www.cnblogs.com/imyalost/p/5726556.html
响应首部字段:http://www.cnblogs.com/imyalost/p/5737024.html
实体首部字段:http://www.cnblogs.com/imyalost/p/5740562.html
首部:首部和方法配合,共同决定和客户端和服务器能做什么事情
一、通用首部
客户端和服务器都可以使用的首部;在客户端、服务器和其他应用程序间提供一些非常有用的通用功能
1.1 通用的信息性首部
提供与报文相关的基本信息
1.2 通用缓存首部
基本的缓存首部
二、请求首部
请求报文特有的首部;为服务器提供一些额外信息,比如:客户端希望接收什么类型的数据、谁发的请求、客户端优先接收类型等
2.1 请求的信息性首部
2.2 Accept首部
2.3 条件请求首部
2.4 安全请求首部
http本身支持一种简单的机制,对请求进行质询/响应认证。此机制要求客户端获取特定资源前,先对自身进行认证,这样可以使事务稍微安全一些
2.5 代理请求首部
三、响应首部
响应首部有自己的首部集,以便为客户端提供信息;比如谁在发送响应,响应的功能,特殊指令等;其有助于客户端处理响应,将来发起更好的请求
3.1 响应的信息性首部
3.2 协商首部
3.3 安全响应首部
http的质询/响应认证机制的响应侧;下面列出基本的质询首部
四、实体首部
应对实体主体部分的首部;比如:说明实体主体部分的数据类型大小等很多信息,很多首部可以用来描述http报文的负荷
4.1 实体的信息性首部
4.2 内容首部
4.3 实体缓存首部
五、扩展首部
非标准的首部,由应用程序开发者创建,但还未添加到已批准的规范中(即使不知道这些首部的含义,http应用程序也要接受它们并对其进行转发)
http协议进阶(五)连接管理
几乎所有的HTTP通信都是由TCP/IP承载的,TCP/IP是全球计算机网络设备都在使用的一种分组交换网络分层协议集。
它的特点是只要连接建立,客户端与服务器之间的报文交换就永远不会丢失、受损或失序。
一、TCP连接
1、TCP是可靠数据通道
TCP是英特网上的可靠连接,TCP为HTTP提供了一条可靠地比特传输通道,从TCP连接一端填入的字节会从另一端以原有的顺序、正确的传送出来。
TCP会按序、无差错的承载HTTP数据,如下图:
2、TCP流是分段的,由IP分组传送
TCP的数据是通过名为IP分组的小数据块发送的,HTTP就是“HTTP over TCP over IP”这个“协议栈”中的最顶层,其安全版本HTTPS就是在HTTP和TCP之间插入一个(TLS或SSL)密码加密层。
如下图所示:
HTTP在传送一条报文时,会以流的形式将报文数据通过打开的TCP连接按序传输。TCP收到数据流之后,将其划分为被称为段的小数据块,封装在IP分组中,通过英特网进行传输。
每个TCP段都是由IP分组承载,从一个IP地址发送到另一个IP地址,其中包括:
①、一个IP分组首部(通常为20字节):包含源和目的IP地址、长度和其他一些标记;
②、一个TCP 段首部(通常为20字节):包含TCP端口号、TCP控制标记以及用于数据排序和完整性检查的数据值;
③、一个TCP数据块(0个或多个字节);
3、保持TCP连接不断运行
TCP通过端口号来保持连接持续不断的运行。IP地址可以连接到正确的计算机,端口号可以连接到正确的应用程序,TCP连接通过四个值来识别:
<源IP地址、源端口号、目的IP地址、目的端口号>
这四个值唯一的定义了一个连接(两条不同的TCP连接不能拥有4个完全相同的地址组件值,不同连接部分可以拥有同样的值)。
4、TCP套接字
操作系统提供了一些操纵TCP连接的编程接口,即套接字API,这个套接字API隐藏了所有的TCP和IP实现细节,下表是一些套接字API的主要接口:
套接字API调用 | 描述 |
s= socket(<sparameters>) | 创建一个新的、未命名、未关联的套接字 |
bind(s,<local IP:port>) | 向套接字赋一个本地端口号和接口 |
connect(s, <remote IP:port>) | 创建一条连接本地套接字与远程主机及端口的连接 |
listen(s,...) | 标识一个本地套接字,使其可以合法接受连接 |
s2 = accept(s) | 等待某人建立一条到本地端口的连接 |
n = read(s, buffer, n) | 尝试从套接字向缓冲区读取n个字节 |
n = write(s, buffer, n) | 尝试从缓冲区中向套接字写入n个字节 |
close(s) | 完全关闭TCP连接 |
shutdown(s,<side>) | 只关闭TCP连接的输出或输入端 |
getsockopt(s,...) | 读取某个内部套接字配置选项的值 |
setsockopt(s,...) | 修改某个内部套接字配置选项的值 |
套接字API允许用户创建TCP的端点数据结构,将其与远程服务器的TCP端点进行连接,并对数据流进行读写。
TCP API隐藏了所有底层网络协议的握手细节,以及TCP数据流与IP分组之间的字段和重装细节。
二、TCP性能
1、HTTP事务的时延
首先来看一个HTTP请求的过程,如下图:
一般来说,相比于建立TCP连接及传输请求和响应报文的时间,事务处理时间可能是很短的(除非客户端或服务端超载或正在处理复杂的动态资源),否则HTTP时延是由TCP网络时延造成的。
http事务时延的原因有以下几点:
①、DNS将服务器域名转换解析为一个IP地址所花费的时间;
②、客户端向服务端发送一个TCP连接请求所造成的时延(一般不会花费很多时间,但如果有很多的HTTP事务的话,时延就会变大);
③、服务端处理请求报文以及回传给客户端,都需要花费一定的时间;
④、服务器回送HTTP响应,也会花费一定的时间;
2、性能聚焦区域
常见的TCP相关时延如下:
①、TCP连接建立握手;
如下图,新建TCP连接时会交换一系列的IP分组,对连接的有关参数进行沟通,如果连接只用来传送少量数据,交换的过程就会严重降低HTTP性能。
②、TCP慢启动拥塞机制;
TCP连接刚建立时为了防止网络突然过载和拥塞,会限制链接的最大速度,如果数据成功传输,会随着时间的推移提高传输速度。
③、数据聚集的Nagle算法;
④、用于捎带确认的TCP延迟确认算法;
⑤、TIME_WAIT时延和端口耗尽;
三、HTTP连接处理
目前现存和常用的连接方法大概有一下四种:
1、串行连接
最早的连接方式,即HTTP事务需要按顺序进行传输,等待服务端完成处理并回传,如下图所示:
这样做有两个缺点:
①、TCP性能时延会不断叠加;
②、在请求处理完成之前,客户端无法对结果进行提前展示,只能被动等待;
2、并行连接
通过多条TCP连接发情并发的HTTP请求,如下图所示:
并行连接有如下几个特点:
①、可能会提高页面加载速度,即连接请求和传输时间重叠,减小了连接时延和传输时延,但每个事务都会打开/关闭一个新的连接,耗费时间和带宽;
②、可以让用户“感觉更快”(与WEB页面渲染的异步展示类似的原理),但实际上,由于TCP慢启动特性的存在,每个新连接的性能都会有所降低,且并行链接数量有限;
③、并行连接不一定比串行连接块(受限于带宽,可能造成资源竞争);
3、持久连接
重用TCP连接,以消除连接及关闭时延,持久连接+并行连接,可能是最高效的连接方式,如下图所示:
持久连接有两种方式,分别为HTTP/1.0+的“Keep-alive”连接,以及HTTP/1.1的“persistent”连接。
Keep-alive:该首部只是请求将连接保持在活跃状态,客户端和服务端可以随时关闭空闲的Keep-alive连接。
限制和规则:
①、必须客户端发送一个Connection:Keep-alive请求首部来激活Keep-alive连接;
②、该首部必须随请求的报文一起发送;
③、只有在确定实体主体部分大小的情况下,连接才能保持在打开状态;
④、代理和网关必须执行Connection首部的规则;
Persistent:该首部默认情况下是激活的,除非特别指明,否则HTTP/1.1假定所有连接都是持久的。
限制和规则:
①、如果需要在事务处理结束后将连接关闭,则应用程序必须向报文中显式的添加一个Connection-close首部;
②、只有当连接上所有报文都有正确的、自动以报文长度时,连接才能持久保持;
③、每个持久连接都只适用于一跳传输;
④、应用程序可以在任意时刻关闭连接,但应该能够从异步关闭中恢复,重试这条请求;
⑤、一个客户端对任何服务器或代理最多只能维护2条持久连接;
4、管道化连接
通过共享TCP连接发起并发的HTTP请求,这也是在持久连接的基础上对性能的一种优化。
原理:在响应到达前,将多条请求放入队列,在高延时网络条件下,可以降低网络环回时间,提高性能。
限制和规则:
①、如果HTTP客户端无法确认连接是持久的,就不应使用管道连接;
②、必须按照与请求相同的顺序回送HTTP响应;
③、客户端必须做好连接会在任何时刻关闭的准备,以及重发所有未完成的管道化请求;
④、HTTP客户端不应用管道化的方式发送非幂等性请求(比如POST);
四种不同连接方式的区别:
某些关于请求和响应首部的字段详细介绍,可以参考《HTTP权威指南》这本书中的内容。。。
http协议进阶(六)代理
web代理服务器是网络的中间实体,位于客户端和服务器之间,扮演“中间人”的角色,作用是在各端点之间来回传送报文。
其原理是:客户端向代理服务器发送请求报文,代理服务器正确的处理请求和连接,然后返回响应;同时代理服务器自身要向web服务器发送请求并接收响应。
即:代理即是服务器,又是客户端。如下图所示:
一、代理的类型
1、私有代理
定义:单个客户端专用的代理被称为私有代理。
私有代理并不常见,但确实存在,比如一些浏览器的辅助产品,一些ISP服务,会在用户的PC上直接运行一些小型代理,以便扩展浏览器特性,提高性能,或者为免费ISP服务提供主机广告等。
2、公共代理
定义:多个客户端共享的代理被称为公共代理,也称为“集中式代理”。
优点:节省成本,效率更高,方便管理,比如:“高速缓存代理服务器”。
二、代理和网关的区别
代理:连接两个或多个使用相同协议的应用程序;
网关:连接两个或多个使用不同协议的端点(可以理解为“协议转换器”);
相同点:代理和网关之间的区别很模糊,代理经常也会做一些协议转换的工作,比如:支持SSL协议、SOCKS防火墙、FTP访问等。
如下图所示:
三、代理的特点
1、资源访问控制
利用过滤器代理进行身份权限验证,或使用代理服务器在大量的web服务器和资源之间实现统一的访问控制策略,创建审核跟踪机制,对所有访问控制功能进行配置,特别体现在大型环境或其他分布式机制的服务中。
2、提高安全性
利用代理服务器在网络中的单一安全节点上限制哪些应用层协议的数据可以流入或者流出,还可以提供用来某些防范和杀毒的挂钩程序,以便对流量进行详细的检查。
3、web缓存
可以利用缓存服务器维护存储常用资源的本地副本,并将其按需提供,以减少连接,缩短连接时延,提高性能。
4、反向代理
代理可以扮演服务器的角色接收发送给web服务器的真实请求,也可以发起与其他服务器的通信,以便按需定位所请求的内容;可以利用反向代理来提高访问web服务器上公共资源时的性能。
或者将其和内容路由功能配合使用,以创建分布式网络。
5、内容路由器
代理服务器可以作为“内容路由器”使用,根据因特网的流量以及内容类型将请求导向特定的web服务器(类似负载均衡),也可以用来实现各种服务级的请求。
6、转码器
代理服务器也可以在将内容发送给客户端之前,修改内容的主体格式,对其进行透明转换,我们称之为转码(比如更改图片格式,文件编码类型等)。
7、匿名
可以利用代理从HTTP报文中删除身份特性(比如IP、cookie),从而提供高度的私密性和安全性。
四、代理服务器的部署
1、出口代理
将代理固定在本地网络出口点,以便控制本地网络和大型英特网之间的流量,提供针对企业外部恶意攻击的防火墙保护;或降低带宽费用,提高性能。
2、访问(入口)代理
将代理放在ISP访问点上,用来处理来自客户端的聚合请求,ISP使用缓存代理来存储常用的资源副本,提高用户下载速度,降低带宽耗费等。
3、反向代理
将代理部署在网络便边缘,web服务器之前,作为反向代理处理所有传给web服务器的请求,并只在必要时向web服务器请求资源;反向代理可以提高服务器的安全性和性能。
4、网络交换代理
将具有足够处理能力的代理服务器放在网络上的对等交换点,通过缓存来减轻网络堵塞,并对流量进行监视。
5、层级代理
通过代理的层次结构将代理级联起来,既可以是静态的也可以是动态的,直到将报文发送到原始服务器。
下图是一个三级代理的层级结构示意图:
下图是一个静态动态代理结合的结构示意图:
6、常见的几种动态选择父代理方式
①、负载均衡
子代理可能会根据当前父代理上的工作负载级别来决定如何选择一个父代理,以达到负载均衡。
②、地理位置附近的路由
子代理可能会选择负责原始服务器所在物理区域的父代理。
③、协议/类型路由
子代理可能根据URI将报文转发到不同的父代理和原始服务器上,某些特定类型的URI可能要通过一些特殊的代理服务器转发请求,以便进行特殊的协议处理。
④、基于订购的路由
如果发布者为高性能服务额外付费了,他们的URI就会被转发到大型缓存或者压缩引擎上,以提高性能。
PS:在不同的产品中,动态父路由逻辑的实现方式各有不同,包括使用配置文件、脚本语言和动态可执行插件等。
五、代理如何获取流量
1、修改客户端配置
很多web客户端都支持手工和自动的代理配置,如果将客户端配置为使用代理服务器,客户端会将HTTP请求直接发送给代理,而不是原始服务器。
2、修改网络,拦截代理
依赖于监视HTTP流量的交换设备及路由设备,在客户端不知情的情况下,对其进行拦截,并将流量导入一个代理。
3、反向代理
修改DNS的命名空间,假扮原始服务器的名称和IP地址,这样所有的请求都会发送给这些反向代理服务器,而不是原始服务器。
4、重定向
可以将某些web服务器的配置为向客户端发送一条HTTP重定向命令,将客户端请求重定向到一个代理上,收到重定向命令后,客户端会与代理进行通信。
以上大概就是关于HTTP协议中代理相关的一些内容整理,涉及到具体实现以及其他方面,可以查阅或者学习相关的具体资料。。。