PHP,DDD,CQRS,Event Sourcing,Kubernetes,Docker,Golang

0%

HTTP协议是如何工作的

浏览网页时HTTP协议的主要应用,但是这并不代表HTTP协议就只能应用于网页的浏览,只要通信的双方都遵守HTTP协议,其就有用武之地。比如腾讯QQ、迅雷等软件都是用HTTP协议(当然还包括其他的协议)。

那么HTTP协议是如何工作的呢? 首先,客户端发送一个请求给服务器,服务器在接收到这个请求后将生成响应返回给客户端。一次HTTP操作成为一个事务,其工作过程可分为四步:

  • 1、客户机与服务器需要建立连接,单击某个超链接,HTTP协议的工作开始。
  • 2、建立连接后,客户机发送一个请求给服务器。格式为:前边是统一资源标识符(URL)、中间是协议版本号,后边是MIME信息(包括请求修饰符、客户机信息和可能的内容)
  • 3、服务器接收到请求后,给予相应的相应信息。格式为:首先是一个状态行(包括信息的协议版本号、一个成功或错误的代码),然后是MIME信息(包括服务器信息、实体信息和可能的内容)
  • 4、客户端接收服务器返回的信息并显示在用户的显示屏上,然后客户机与服务器断开连接。

如果以上过程中的某一步出现错误,产生错误的信息将返回到客户端,有显示屏输出。对于用户来说,这些过程是由HTTP协议自己完成的,用户只要用鼠标点击等待信息显示就可以了。

请求

HTTP请求由三部分组成:请求行、消息报头、请求正文。请求行以一个请求方式符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式为:Method Request-URI HTTP-Version CRLF 比如我请求本站某页面:http://www.veitor.net/cate/bianchengyuyan 请求行如图 QQ截图20150106220345 参数说明:

  • Method:请求方法。截图中为GET。
  • Request-URI:一个统一资源标识符,截图中为/cate/bianchengyuyan
  • HTTP-Version:请求的HTTP协议版本,截图中为1.1
  • CRLF:回车和换行符

响应

在接收和解释请求消息后,服务器返回一个HTTP响应消息。HTTP相应也由三个部分组成。分别是:状态行、消息报头、响应正文。状态行格式为:HTTP-Version Status-Code Reason-Phrase CRLF 比如我请求本站某页面:http://www.veitor.net/cate/bianchengyuyan QQ截图20150106221255 参数说明如下:

  • HTTP-Version:服务器HTTP协议的版本,截图中为1.1
  • Status-Code:服务器发回的响应状态码,截图中为200
  • Reason-Phrase:状态代码的文本描述,截图中为OK

其中状态代码由三位数字组成,第一个数字定义了响应的类别,有五种可能取值:

  1. 1xx:指示信息——请求已接收,继续处理。
  2. 2xx:成功——请求已被成功接收、理解、接受
  3. 3xx:重定向——要完成请求必须进行更进一步的操作
  4. 4xx:客户端错误——请求有语法错误或请求无法实现
  5. 5xx:服务器错误——服务器未能实现合法的请求

常见的状态码、状态描述和说明如下:

  • 200 OK:客户端请求成功
  • 400 Bad Request:客户端请求有语法错误,不能被服务器所理解
  • 401 Unauthorize:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
  • 403 Forbidden:服务器收到请求,但是拒绝提供服务
  • 404 Not Found:请求资源不存在,例如输入了错误的URL
  • 500 Internal Server Error:服务器发生不可预期的错误
  • 503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常

报头

HTTP消息报头包括普通报头、请求报头、响应报头、实体报头。每个报头域组成形式如下:

  1. 普通报头中有少数报头域用于所有的请求和响应消息,但并不用于被传输的实体,只用于传输的消息(如缓存控制、连接控制)

  2. 请求报头允许客户端向服务器端传递请求的附加信息以及客户端自身的信息(如UA头、Accept等)

  3. 响应报头允许服务器传递不能放在状态行中的附加响应信息,以及关于服务器的信息和对Request-URL所标的资源进行下一步访问的信息(如Location)

  4. 实体报头定义了关于实体正文和请求所标识的资源的元信息,例如有无实体正文。

    比较重要的几个报头如下(可以结合着上面的截图看):

  • Host:头域指定请求资源的Internet主机和端口号,必须表示请求URL的原始服务器或网关的位置。HTTP1.1请求必须包含主机头域,否则系统会以400状态码返回。

  • User-Agent:简称UA,内容包含发出请求的用户信息。通常UA包含浏览者的信息,主要是浏览器的名称版本和所用的操作系统。在上面的截图中可以看到,我的客户端电脑使用的是Gecko渲染引擎的浏览器,我用的Chrome,操作系统为Windows NT6.1的内核,即Windows 7操作系统(内核版本号和操作系统代号不是一一对应的)。这个UA头不仅仅是使用浏览器才存在,只要使用了基于HTTP协议的客户端软件都会发送这个请求,无论是手机端还是PDA等,这个UA头是辨别客户端所用设备的重要依据

  • Accept:告诉服务器可以接受的文件格式,通常这个值在各种浏览器中都差不多。不过Wap浏览器所能接受的格式要少一点,这也是用来区分WAP和计算机浏览器的主要依据之一。随着WAP浏览器的升级,其已经和计算机浏览器越来越接近,因此这个判断所起的作用越来越弱。

  • Cookie:Cookie分两种,一种是客户端向服务器端发送的,使用Cookie报头,用来标记一些信息;另一种是服务器发送给浏览器的,报头为Set-Cookie。两者的区别是Cookie报头的value里可以有多个cookie值,并且不需要显式指定domain等。而set-Cookie报头里一条记录只能有一个Cookie的value,需要指明domain、path等

  • Cache-Control:指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会选择另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached;响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age

  • Referer:头域允许客户端指定请求URI的资源地址,这可以允许服务器生成回退链表,可以用来登录、优化缓存等。也允许废除的或错误的连接由于维护的目的而被追踪。如果请求的URI没有自己的URI地址,Referer不能被发送。如果指定的是部分URI地址,则此地址应该是一个相对地址。Referer通常是流量统计系统来记录来访者地址的参数。

  • Content-Length:内容长度

  • Content-Range:响应的资源范围。可以在每次请求中标记请求的资源范围,在连接断开重连时,客户端只请求该资源未下载的部分,而不是重新请求整个资源,实现断点续传。迅雷就是基于这个原理,使用多线程分段读取网络上的资源,最后再合并。

  • Accept-Encoding:指定所能接受的编码方式。通常服务器会对页面进行GZIP压缩后再输出以减少流量,一般浏览器均支持对这种压缩后的数据进行处理。但对于我们来说,如果不想接受到这些看似“乱码”的数据,可以指定不接受任何服务器端压缩处理,要求其原样返回

  • 自定义报头:在HTTP消息中,也可以使用一些HTTP1.1正式规范里没有定义的头字段,这些头字段统称为自定义的HTTP头或者扩展头。比如上面截图中X-Powered-By字段,这是由服务器发送的。在PHP里,使用header函数即可实现。

    参考:《PHP核心技术与最佳实践》