HTTP协议的一些基础知识的学习

2016-07-07 | 阅读

HTTP协议的学习

超文本传输协议HTTP(HyperText Transfer Protocol) 是互联网上应用最为广泛的一种网路协议. HTTP是应用层协议.

HTTP是一个客户端和服务器端请求和应答的标准TCP, 客户端是终端用户,服务器端是网站. 客户端通过 web浏览器,网络爬虫或者其他工具,来向服务器指定端口发送HTTP请求. 我们称客户端说使用的这个工具,叫做用户代理,也就是user agent . 应答服务器上存放一些资源,我们称应答服务器为源服务器origin server .

通常,由HTTP客户端发起一个请求,建立一个到服务器指定端口的TCP连接,HTTP服务器则在这个端口监听服务器端发过来的请求.一旦接到请求,服务器就会向客户端发送一个状态行,如HTTP/1.1 200OK,和一些响应的消息.

HTTP协议请求的资源由 统一资源标识符Uniform Resource Identifiers来标识.

HTTP协议使用TCP来实现,所以不仅能保证计算机正确快速的传输超文本文档,还能确定传输文档中的哪一部分,以及决定各部分的传输顺序.

HTTP请求中间会出现三种形式的中介 :

  • 代理Proxy : 根据URI的绝对格式来接受请求,重写消息,通过URI标识把已格式化过的请求发送到服务器.
  • 网关Gateway : 一个接受代理,作为其他服务器的上层,可以将请求翻译给下层的服务器协议.
  • 通道Tunnel : 通道作为一个不改变消息的接受代理,作为一些其他服务器的上层.如通过防火墙时,即使用了通道.

报文格式

HTTP的请求报文由 请求行request line ,请求头部 header ,一个空行 和 请求数据4个部分组成 :

请求行以方法字段开始 ,方法字段即表示请求类型,如GET POST. 后面是URL字段和HTTP协议版本字段,并以CRLF结尾(CRLFCarriage-Return Line-Feed 回车加换行,即\r\n) ,使用空格做分割符,一个请求行的例子GET /form.html HTTP/1.1 (CRLF).

请求头部由 键值对组成 ,每行一对,关键字与值用冒号:分割,请求头部告知服务器有关服务器请求的相关信息。

空行也就是一个单独的CRLF,告知服务器以下不再有请求头.

请求数据一般放置POST时的客户填写表单.

响应报文也由4个部分组成,分别是 : 状态行,响应头,空行,响应正文.

第一行是状态行,用状态信息替代了请求信息. 状态行记录报文信息与版本,和状态码与状态描述,通过空格分离.状态码来说明请求资源的情况。 一个响应的状态行如 : HTTP/1.1 200 OK

响应头部一般放置一些有关服务器的信息,和请求URI指定的资源的更近一步的方法,如请求头部一样.

响应正文与请求正文一样是一个实体. 实体报文域上,也分为实体头和实体主体。 实体头部定义了实体主体的元信息.一般为 Content-TypeContent-Length这样决定实体内容和实体长度的关键数据,但是并不与正文放在一起,而是将所有头部都放在头部字段的位置,也就是响应正文实体的头部也会放在响应头部的位置。 而实体主体被放在响应正文中传输。

HTTP头信息

HTTP的头域,包括通用头,请求头,响应头和实体头,这是根据功能划分的,头部信息统一放在 请求头部或者响应头部中传输.

通用头

通用头包含请求和响应消息都支持的头域:

  • Pragma : 用于包含特定执行指令.最常用的就是Pragma:no-cache,与Cache-Control:no-cache相同
  • Connection : 表示是否需要持久连接.因为TCP的三次握手耗时耗资源,所以HTTP1.1最主要的改进就是支持持续连接。有三个值:
    • Close : 告知Web服务器或者代理服务器,在完成本次请求后, 断开连接.
    • Keepalive : 告知服务器,在完成本次请求后,保持连接.
    • Keep-Alive : 如果浏览器请求保持连接,则该头部表示 Web服务器将会保持连接的时间, 如 Keep-Alive:300.

    HTTP1.1中,默认选择Keepalive,持续连接.

  • Date : 表示消息发送的时间.服务器响应中必须包含这个头部,用于缓存评估响应新鲜度.一般格式为 Date:Mon, 31 Dec 2001 04:25:57 GMT
  • Transfer-Encoding : 服务器表明自己对响应消息体 做的编码, 如是否分块 : Transfer-Encoding: chunked.
  • Upgrade : 指定一个可能完全不同的协议 . 如一个HTTP/1.1的客户端可以向服务器发送一条HTTP/1.0的请求,其中 包含值为HTTP/1.1Upgrade头部,这样来测试服务器是否可以使用HTTP/1.1.
  • Via : 列出从客户端 到 服务器 或者 服务器到客户端 的响应, 经过了哪些代理服务器,以及使用什么协议发送的请求. 当客户端请求到达第一个代理服务器时,该服务器会在自己发送的请求里面添加一个Via头部,并添加上自己的相关信息,之后的代理服务器也一样,依次补充Via内容。
  • Cache-Control : 指定请求和响应遵循的缓存机制. 请求的缓存指令包括no-cacheno-storemax-agemax-stalemin-freshonly-if-cached,响应消息中的指令包括publicprivateno-cacheno-storeno-transformmust-revalidateproxy-revalidatemax-age,s-maxage。指令含义如下:

    • no-cache : 指示请求和响应的消息不能缓存,实际上是可以存储到本地缓存区中,只是在与服务器进行新鲜度验证之前,缓存不能将其提供给客户端使用。 即缓存必须经过服务器的验证后,才能使用。缓存数据,但是每次使用前,都去与服务器校验是否有更新。
    • no-store : 禁止缓存,出于隐私考虑。
    • max-age : 缓存时间,表示缓存的过期时间,如果缓存没有过期,则数据由缓存数据返回。
    • min-fresh : 至少在未来规定的时间内 数据要保持新鲜.与max-age功能相似。
    • max-stale : 指示客户端可以接收过期的缓存,过期时间不超过 指定秒数。
    • only-if-cached : 从缓存中获取,且不关心缓存是否新鲜。
    • Pulic : 可以被任何缓存区缓存。
    • Private : 针对用户缓存,即可以指定一个字段 ,如 private - "username" ,然后导致一份私有缓存,不被共享。 一般是指只有客户端可以缓存,代理服务器不应该缓存。
    • must-revalidate : 如果缓存过了新鲜期,则重新验证,而不是试图返回一个不在新鲜期的缓存。
    • proxy-revalidate : 限制上与must-revalidate类似,但是要排除用户代理的缓存。
    • s-maxage : 仅应用于共享缓存,不应用于 用户代理的本地缓存和针对单个用户的缓存。

请求头

请求头一般用来说明 客户端信息. 有以下几种

  • Accept : 客户端需要的响应数据的类型, */*表示任何数据, type/*表示该类型下的所有子类型。
  • Accept-Charset : 客户端需要的字符集,UTF-8 GBK之类。
  • Accept-Encoding : 客户端想要的 编码类型,这里指的不是UTF-8这样的字符集,而是 一般用来指定压缩方式,即是否使用gzip
  • Accept-Language : 声明需要的语言.
  • Authorization : 当客户端收到服务器的 WWW-Authenticate时,用该头部来表明自己的身份信息.
  • If-Match : 如果对象的Etag匹配到了, 才去执行请求动作,获取文档, 参数是 ETag.
  • If-None-Match : 如果对象的ETag没有匹配,才去执行请求动作,获取文档.
  • If-Modified-Since : 如果请求的对象在这个指定的时间后 修改了, 才执行请求的动作,否则返回代码 304, 告知浏览器对象没有修改. 如 If-Modified-Since:Thu, 10 Apr 2008 09:14:42 GMT.
  • If-Unmodified-Since : 如果请求的对象在该头部指定的时间后 没有修改,才执行请求的动作.
  • Range : 分段取数据,告诉服务器这次请求的范围,或者多个子范围, 如 bytes=0-499表示前500个字节 , bytes=0-0,-1 表示第一个字节和最后一个字节.
  • If-Range : 浏览器告诉服务器, 如果请求的对象没有改变,则将缺少的部分返回,如果对象改变了,就将整个对象返回. 浏览器通过 Etag和修改时间来让服务器判断对象是否改变,总是与Range一起使用
  • Proxy-Authenticate : 代理服务器响应浏览器,要求其提供代理身份验证信息.
  • Proxy-Authorization : 浏览器响应代理服务器的身份验证请求,提供的身份信息.
  • Host : 客户端指定想要访问的域名以及端口号.
  • Referer : 浏览器向服务器表明 自己是从哪个页面跳转到当前页面的.
  • User-Agent : 浏览器表明自己的身份 ,一般记录系统和浏览器信息.
  • From : 发起请求的用户的 Email
  • Expect : 指定请求的服务器的行为
  • Cookie : 将请求域名下的所有Cookie值一起发送给服务器.

响应头

  • Age : 当代理服务器用自己缓存的实体去响应请求时,用该头部表明 实体的生命.
  • Server : 表明服务器的版本和信息. 如 Server:Apache/2.0.61 (Unix)
  • Accept-Ranges : 服务器表示是否自己接受了 Range的请求,如果接受了,会用bytes来标记部分,设置none表示不接受.
  • Vary : 服务器让 Chache服务器验证请求头信息,是否匹配这个Vary,以保证正确缓存. 如 响应头Content-Encoding: gzip; Vary: Content-Encoding,表示缓存服务器缓存了这个数据后,对于新的请求过来时,要验证新的请求是否满足之前响应中的 Content-Encoding选项,以避免实体被缓存服务器发给不支持解压的服务器.
  • WWW-Authenticat : 指定客户要在Authorization中提供的授权信息, 这是在 401状态下,会出现的响应头.
  • Warning : 关于响应状态的补充信息.
  • Public : 列举服务器说支持的方法集, 如 Public: OPTIONS,MGET,MHEAD,GET,HEAD
  • Retry-After : 与状态编码503结合, 503表示无法提供服务,而Retry-After表示再次请求需要等待的时间.
  • Refresh : 指定一定时间后重定向到指定地址,如 Refresh: 5; url=http://www.baidu.com
  • Set-Cookie : 服务器告知客户端要设置的 cookie.

实体头

实体头主要来描述有关实体及其内容的信息.

  • Allow : 服务器支持的方法, 如GET POST
  • Location : 进行重定向, 告知用户去一个新的地方获取文档. 一般状态码为302.
  • Content-Base : 解析主体中的相对URL时 ,使用的基础URL.
  • Content-Encoding : 服务器表明自己使用的压缩方式, 如 Content-Encoding:gzip
  • Content-Language : 服务器告知浏览器 主体使用的语言.
  • Content-Length : 主体的长度.
  • Content-Locaiton : 指明资源的另一个地址,但是不进行重定向.
  • Content-MD5 : 主体的MD5校验和.
  • Content-Range : 指明 主体传输的范围.
  • Content-Type : 指明 主体的对象类型, 如 Content-Type:application/xml
  • Etag : 一个对象的标志值. 如一个html文件,被修改了,则其Etag也会修改,供服务器判断一个对象是否改变.
  • Expires : 服务器指明实体何时过期. 这是 HTTP1.0 中的内容,1.1中使用Cache-Control来控制.
  • Last-Modified : 服务器记录的对象最后修改时间, 比如文件最后修改时间,或者动态页面最后产生时间, 与ETag一样,用于校验对象是否被修改.

请求类型

目前HTTP中有8种请求类型,但事实上只有两种常用的 ,GETPOST,总共8种为:

  • OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送’*‘的请求来测试服务器的功能性。
  • HEAD:向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。
  • GET:向特定的资源发出请求。
  • POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。
  • PUT:向指定资源位置上传其最新内容。
  • DELETE:请求服务器删除Request-URI所标识的资源。
  • TRACE:回显服务器收到的请求,主要用于测试或诊断。
  • CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

我们主要关注于GETPOST,两者最主要的区别在于 ,GET将请求参数放在URL中,即会放在request line中, 而POST将请求参数封装在BODY中,所以可以传输大量数据. 所以GET请求一般没有请求内容.

响应状态码

状态码的第一位数字定义响应类型。第一位数字有五种值:

  • 1xx : 报告的 , 接收到请求,继续进程.
  • 2xx : 成功 , 步骤成功接收,被理解,并被接受
  • 3xx : 重发 , 为了完成请求,必须采取进一步措施.
  • 4xx : 客户端出错, 请求包括错的顺序或不能完成.
  • 5xx : 服务器出错 , 服务器无法完成显然有效的请求.

接下来抄录所有的状态码 :

1xx:信息
消息
描述
100 Continue
服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。
101 Switching Protocols
服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。
2xx:成功
消息
描述
200 OK
请求成功(其后是对GET和POST请求的应答文档。)
201 Created
请求被创建完成,同时新的资源被创建。
202 Accepted
供处理的请求已被接受,但是处理未完成。
203 Non-authoritative Information
文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝。
204 No Content
没有新文档。浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。
205 Reset Content
没有新文档。但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容。
206 Partial Content
客户发送了一个带有Range头的GET请求,服务器完成了它。
3xx:重定向
消息
描述
300 Multiple Choices
多重选择。链接列表。用户可以选择某链接到达目的地。最多允许五个地址。
301 Moved Permanently
所请求的页面已经转移至新的url。
302 Found
所请求的页面已经临时转移至新的url。
303 See Other
所请求的页面可在别的url下被找到。
304 Not Modified
未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
305 Use Proxy
客户请求的文档应该通过Location头所指明的代理服务器提取。
306 Unused
此代码被用于前一版本。目前已不再使用,但是代码依然被保留。
307 Temporary Redirect
被请求的页面已经临时移至新的url。
4xx:客户端错误
消息
描述
400 Bad Request
服务器未能理解请求。
401 Unauthorized
被请求的页面需要用户名和密码。
401.1
登录失败。
401.2
服务器配置导致登录失败。
401.3
由于 ACL 对资源的限制而未获得授权。
401.4
筛选器授权失败。
401.5
ISAPI/CGI 应用程序授权失败。
401.7
访问被 Web 服务器上的 URL 授权策略拒绝。这个错误代码为 IIS 6.0 所专用。
402 Payment Required
此代码尚无法使用。
403 Forbidden
对被请求页面的访问被禁止。
403.1
执行访问被禁止。
403.2
读访问被禁止。
403.3
写访问被禁止。
403.4
要求 SSL。
403.5
要求 SSL 128。
403.6
IP 地址被拒绝。
403.7
要求客户端证书。
403.8
站点访问被拒绝。
403.9
用户数过多。
403.10
配置无效。
403.11
密码更改。
403.12
拒绝访问映射表。
403.13
客户端证书被吊销。
403.14
拒绝目录列表。
403.15
超出客户端访问许可。
403.16
客户端证书不受信任或无效。
403.17
客户端证书已过期或尚未生效。
403.18
在当前的应用程序池中不能执行所请求的 URL。这个错误代码为 IIS 6.0 所专用。
403.19
不能为这个应用程序池中的客户端执行 CGI。这个错误代码为 IIS 6.0 所专用。
403.20
Passport 登录失败。这个错误代码为 IIS 6.0 所专用。
404 Not Found
服务器无法找到被请求的页面。
404.0
(无)–没有找到文件或目录。
404.1
无法在所请求的端口上访问 Web 站点。
404.2
Web 服务扩展锁定策略阻止本请求。
404.3
MIME 映射策略阻止本请求。
405 Method Not Allowed
请求中指定的方法不被允许。
406 Not Acceptable
服务器生成的响应无法被客户端所接受。
407 Proxy Authentication Required
用户必须首先使用代理服务器进行验证,这样请求才会被处理。
408 Request Timeout
请求超出了服务器的等待时间。
409 Conflict
由于冲突,请求无法被完成。
410 Gone
被请求的页面不可用。
411 Length Required
"Content-Length" 未被定义。如果无此内容,服务器不会接受请求。
412 Precondition Failed
请求中的前提条件被服务器评估为失败。
413 Request Entity Too Large
由于所请求的实体的太大,服务器不会接受请求。
414 Request-url Too Long
由于url太长,服务器不会接受请求。当post请求被转换为带有很长的查询信息的get请求时,就会发生这种情况。
415 Unsupported Media Type
由于媒介类型不被支持,服务器不会接受请求。
416 Requested Range Not Satisfiable
服务器不能满足客户在请求中指定的Range头。
417 Expectation Failed
执行失败。
423
锁定的错误。
5xx:服务器错误
消息
描述
500 Internal Server Error
请求未完成。服务器遇到不可预知的情况。
500.12
应用程序正忙于在 Web 服务器上重新启动。
500.13
Web 服务器太忙。
500.15
不允许直接请求 Global.asa。
500.16
UNC 授权凭据不正确。这个错误代码为 IIS 6.0 所专用。
500.18
URL 授权存储不能打开。这个错误代码为 IIS 6.0 所专用。
500.100
内部 ASP 错误。
501 Not Implemented
请求未完成。服务器不支持所请求的功能。
502 Bad Gateway
请求未完成。服务器从上游服务器收到一个无效的响应。
502.1
CGI 应用程序超时。 ·
502.2
CGI 应用程序出错。
503 Service Unavailable
请求未完成。服务器临时过载或当机。
504 Gateway Timeout
网关超时。
505 HTTP Version Not Supported
服务器不支持请求中指明的HTTP协议版本。

TCP 的三次握手.

  1. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
  2. 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  3. 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

三次握手后,TCP就建立了持久连接,当要断开连接时,需要进行四次挥手的过程.

TCP的四次挥手

  1. 客户端发送一个 FIN ,用来告知服务器,要关闭数据传输了.
  2. 服务器收到这个FIN,并发送一个ACK回去,确认序号为收到序号加1.但是服务器并没有立即结束,还有一些数据要传输和一些清理操作要作.这个ACK只是表示服务器收到了客户端的FIN..
  3. 服务器确认要管理与客户端的连接了, 便发送一个FIN给客户端.
  4. 客户端回复一个ACK给服务器,并将确认序号加1, 确认连接已经完全断开.

在关闭连接时,有四次握手的原因,就在于服务器端在收到FIN后,可能还有一些数据要继续传输,所以先发送一个ACK来表示已经接受到客户端的请求,但是服务器端处理好剩余数据后,才会发送一个FIN来确认断开连接.