• Http协议详解


    (1)HTTP协议:
    1. HTTP简介
    HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。
    2. 计算机相互之间的通信
    互联网的关键技术就是TCP/IP协议。两台计算机之间的通信是通过TCP/IP协议在因特网上进行的。
    实际上这个是两个协议:TCP : Transmission Control Protocol 传输控制协议和IP: Internet Protocol  网际协议。
            IP:计算机之间的通信
            IP协议是计算机用来相互识别的通信的一种机制,每台计算机都有一个IP.用来在internet上标识这台计算机。  IP 负责在因特网上发送和接收数据包。通过 IP,消息(或者其他数据)被分割为小的独立的包,并通过因特网在计算       

                机之间传送。IP 负责将每个包路由至它的目的地。

    IP协议仅仅是允许计算机相互发消息,但它并不检查消息是否以发送的次序到达而且没有损坏(只检查关键的头数据)。为了提供消息检验功能,直接在IP协议上设计了传输控制协议TCP.
         TCP : 应用程序之间的通信
    TCP确保数据包以正确的次序到达,并且尝试确认数据包的内容没有改变。TCP在IP地址之上引端口(port),它允许计算机通过网络提供各种服务。一些端口号为不同的服务保留,而且这些端口号是众所周知。
           服务或者守护进程:在提供服务的机器上,有程序监听特定端口上的通信流。例如大多数电子邮件通信流出现在端口25上,用于www的HTTP通信流出现在80端口上。
           当应用程序希望通过 TCP 与另一个应用程序通信时,它会发送一个通信请求。这个请求必须被送到一个确切的地址。在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信,占用两个计算机之间整个的通信线路。TCP 用于从应用程序到网络的数据传输控制。TCP 负责在数据传送之前将它们分割为 IP 包,然后在它们到达的时候将它们重组。
           TCP/IP 就是TCP 和 IP 两个协议在一起协同工作,有上下层次的关系。
    TCP 负责应用软件(比如你的浏览器)和网络软件之间的通信。IP 负责计算机之间的通信。TCP 负责将数据分割并装入 IP包,IP负责将包发送至接受者,传输过程要经IP路由器负责根据通信量、网络中的错误或者其他参数来进行正确地寻址,然后在它们到达的时候重新组合它们。
    3. HTTP协议所在的协议层
          HTTP是基于TCP协议之上的。在TCP/IP协议参考模型的各层对应的协议如下图,其中HTTP是应用层的协议。
    4. HTTP请求响应模型  
           HTTP由请求和响应构成,是一个标准的客户端服务器模型(B/S)。HTTP协议永远都是客户端发起请求,服务器回送响应。见下图:
          HTTP是一个无状态的协议。无状态是指客户机(Web浏览器)和服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后服务器返回响应(response),连接就被关闭了,在服务器端不保留连接的有关信息.HTTP遵循请求(Request)/应答(Response)模型。客户机(浏览器)向服务器发送请求,服务器处理请求并返回适当的应答。所有HTTP连接都被构造成一套请求和应答。
    5. HTTP工作过程     
         一次HTTP操作称为一个事务,其工作整个过程如下:
      1 ) 、地址解析,
         如用客户端浏览器请求这个页面:http://localhost.com:8080/index.htm
         从中分解出协议名、主机名、端口、对象路径等部分,对于我们的这个地址,解析得到的结果如下:
         协议名:http
         主机名:localhost.com
         端口:8080
         对象路径:/index.htm
          在这一步,需要域名系统DNS解析域名localhost.com,得主机的IP地址。
      2)、封装HTTP请求数据包
         把以上部分结合本机自己的信息,封装成一个HTTP请求数据包
    3)封装成TCP包,建立TCP连接(TCP的三次握手)
           在HTTP工作开始之前,客户机(Web浏览器)首先要通过网络与服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能,才能进行更层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80。这里是8080端口
    4)客户机发送请求命令
           建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可内容。
    5)服务器响应
         服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。
            实体消息是服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据
    6)服务器关闭TCP连接
         一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码
        Connection:keep-alive
       TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。
    6. HTTP协议栈中各层数据流     
    首先我们看看客户端请求的时候,数据在各层协议的数据组织如下图:
    而服务器解析客户机请求就是反向操作的过程,如下图:
    客户机发起一次请求的时候:
           客户机会将请求封装成http数据包-->封装成TCP数据包-->封装成IP数据包--->封装成数据帧--->硬件将帧数据转换成bit流(二进制数据)-->最后通过物理硬件(网卡芯片)发送到指定地点。
           服务器硬件首先收到bit流....... 然后转换成ip数据包。于是通过ip协议解析Ip数据包,然后又发现里面是tcp数据包,就通过tcp协议解析Tcp数据包,接着发现是http数据包通过http协议再解析http数据包得到数据。

    6. HTTPS实现原理   
    HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL。其所用的端口号是443
             SSL:安全套接层,是netscape公司设计的主要用于web的安全传输协议。这种协议在WEB上获得了广泛的应用。通过证书认证来确保客户端和网站服务器之间的通信数据是加密安全的。
    有两种基本的加解密算法类型:
    1)对称加密(symmetrcic encryption):密钥只有一个,加密解密为同一个密码,且加解密速度快,典型的对称加密算法有DES、AES,RC5,3DES等;
           对称加密主要问题是共享秘钥,除你的计算机(客户端)知道另外一台计算机(服务器)的私钥秘钥,否则无法对通信流进行加密解密。解决这个问题的方案非对称秘钥。
    2)非对称加密:使用两个秘钥:公共秘钥和私有秘钥。私有秘钥由一方密码保存(一般是服务器保存),另一方任何人都可以获得公共秘钥。
          这种密钥成对出现(且根据公钥无法推知私钥,根据私钥也无法推知公钥),加密解密使用不同密钥(公钥加密需要私钥解密,私钥加密需要公钥解密),相对对称加密速度较慢,典型的非对称加密算法有RSA、DSA等。
       下面看一下https的通信过程:
    过程大致如下:
    1) SSL客户端通过TCP和服务器建立连接之后(443端口),并且在一般的tcp连接协商(握手)过程中请求证书。即客户端发出一个消息给服务器,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,SSL的服务器端会回应一个数据包,这里面确定了这次通信所需要的算法,然后服务器向客户端返回证书。(证书里面包含了服务器信息:域名。申请证书的公司,公共秘钥)。                
    2)Client在收到服务器返回的证书后,判断签发这个证书的公共签发机构,并使用这个机构的公共秘钥确认签名是否有效,客户端还会确保证书中列出的域名就是它正在连接的域名。
    3)如果确认证书有效,那么生成对称秘钥并使用服务器的公共秘钥进行加密。然后发送给服务器,服务器使用它的私钥对它进行解密,这样两台计算机可以开始进行对称加密进行通信。
    https通信的优点:
    1)客户端产生的密钥只有客户端和服务器端能得到;
    2)加密的数据只有客户端和服务器端才能得到明文;
    3)客户端到服务端的通信是安全的。

    http协议请求头、响应头、缓存:
    1. HTTP请求格式     
           做过Socket编程的人都知道,当我们设计一个通信协议时,“消息头/消息体”的分割方式是很常用的,消息头告诉对方这个消息是干什么的,消息体告诉对方怎么干。HTTP协议传输的消息也是这样规定的,每一个HTTP包都分为HTTP头和HTTP体两部分,消息体是可选的,而消息头是必须的。每当我们打开一个网页,在上面点击右键,选择“查看源文件”,这时看到的HTML代码就是HTTP的消息体,那么消息头可以通过浏览器的开发工具或者插件可以看到,如果火狐的Firebug,IE的Httpwatch。
          客户端通过发送 HTTP 请求向服务器请求对资源的访问。 它向服务器传递了一个数据块,也就是请求信息,HTTP 请求由三部分组成:请求行、  请求头和请求正文。
    请求行:请求方法 URI   协议/版本
    请求头(Request Header)
    请求正文
    下面是一个HTTP请求的数据:
    POST /index.php HTTP/1.1
    Host: localhost
    User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-cn,zh;q=0.5
    Accept-Encoding: gzip, deflate
    Connection: keep-alive
    Referer: http://localhost/
    Content-Length:25
    Content-Type:application/x-www-form-urlencodedusername=aa&password=1234

    1、请求行:请求方法URI协议/版本
    请求的第一行是“方法 URL  协议/版本”,并以回车换行作为结尾。请求行以空格分隔。格式如下:
    POST /index.php HTTP/1.1
    以上代码中“GET”代表请求方法,“/index.php”表示URI,“HTTP/1.1代表协议和协议的版本。
            根据HTTP标准,HTTP请求可以使用多种请求方法。例如:HTTP1.1支持7种请求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TARCE。在Internet应用中,最常用的方法是GET和POST。
             URL完整地指定了要访问的网络资源,通常只要给出相对于服务器的根目录的相对目录即可,因此总是以“/”开头,最后,协议版本声明了通信过程中使用HTTP的版本。  
    请求方法
    在 HTTP 协议中,HTTP 请求可以使用多种请求方法,这些方法指明了要以何种方式来访问 Request-URI 所标识的资源。HTTP1.1 支持的请求方法如下表所示:
    HTTP1.1 中的请求方式:
    方法            作用
    GET          请求获取由 Request-URI 所标识的资源
    POST        请求服务器接收在请求中封装的实体,并将其作为由 Request-Line 中的 Request-URI 所标识的资源的一部分
    HEAD        请求获取由 Request-URI 所标识的资源的响应消息报头
    PUT          请求服务器存储一个资源,并用 Request-URI 作为其标识符
    DELETE     请求服务器删除由 Request-URI 所标识的资源
    TRACE      请求服务器回送到的请求信息,主要用于测试或诊断
    CONNECT     保留将来使用
    OPTIONS     请求查询服务器的性能,或者查询与资源相关的选项和需求
    重点介绍 GET、POST 和 HEAD 三个方法:
    (1)GET
            GET 方法用于获取由 Request-URI 所标识的资源的信息,常见的形式是:
            GET Request-URI HTTP/1.1
            GET方法是默认的HTTP请求方法,例如当我们通过在浏览器的地址栏中直接输入网址的方式去访问网页的时候,浏览器采用的就是 GET 方法向服务器获取资源。
            我们可以使用GET方法来提交表单数据,用GET方法提交的表单数据只经过了简单的编码,同时它将作为URL的一部分向服务器发送,因此,如果使用GET方法来提交表单数据就存在着安全隐患上。例如:
             Http://localhost/login.php?username=aa&password=1234
            从上面的URL请求中,很容易就可以辩认出表单提交的内容。(?之后的内容)另外由于GET方法提交的数据是作为URL请求的一部分所以提交的数据量不能太大。这是因为浏览器对url的长度有限制
           各种浏览器也会对url的长度有所限制,下面是几种常见浏览器的url长度限制:(单位:字符)
    IE : 2803
    Firefox:65536
    Chrome:8182
    Safari:80000
    Opera:190000

    (2)POST
              POST方法是GET方法的一个替代方法,它主要是向Web服务器提交表单数据,尤其是大批量的数据。 在请求头信息结束之后的两个回车换行之后(实际是空一行),就是表单提交的数据。如上面提到的post表单数据:
            username=aa&password=1234
    POST方法克服了GET方法的一些缺点。通过POST方法提交表单数据时,数据不是作为URL请求的一部分而是作为标准数据传送给Web服务器,这就克服了GET方法中的信息无法保密和数据量太小的缺点。因此,出于安全的考虑以及对用户隐私的尊重,通常表单提交时采用POST方法。从编程的角度来讲,如果用户通过GET方法提交数据,则数据存放在QUERY_STRING环境变量中,而POST方法提交的数据则可以从标准输入流中获取。
    GET与POST方法有以下区别:
          1、  在客户端,Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放在HTTP包的body中。
         2、 GET方式提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST则没有此限制。
         3、安全性问题。正如在(1)中提到,使用 Get 的时候,参数会显示在地址栏上,而 Post 不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用 get;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用 post为好。
         4.、服务器取值方式不一样。GET方式取值,如php可以使用$_GET来取得变量的值,而POST方式通过$_POST来获取变量的值。
    (3)HEAD
         HEAD 方法与 GET 方法几乎是相同的,它们的区别在于 HEAD 方法只是请求消息报头,而不是完整的内容。对于 HEAD 请求的回应部分来说,它的 HTTP 头部中包含的信息与通过 GET 请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到 Request-URI 所标识的资源的信息。这个方法通常被用于测试超链接的有效性,是否可以访问,以及最近是否更新。
        要注意的是,在 HTML 文档中,书写 get 和 post,大小写都可以,但在 HTTP 协议中的 GET 和 POST 只能是大写形式。

    2. 请求头

    每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。
    HTTP最常见的请求头如下:
    Transport 头域
    Connection:
    作用:表示是否需要持久连接。
    如果服务器看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,服务器需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入 ByteArrayOutputStream,然后在正式写出内容之前计算它的大小;
    例如: Connection: keep-alive   当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的  网页,会继续使用这一条已经建立的连接
    例如:  Connection: close  代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭,  当客户端再次发送Request,需要重新建立TCP连接。
    Host(发送请求时,该报头域是必需的)
    Host请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的。
    eg:http://:localhost/index.html
    浏览器发送的请求消息中,就会包含Host请求报头域,如下:
    Host:localhost
    此处使用缺省端口号80,若指定了端口号8080,则变成:Host:localhost:8080
    Client 头域
    Accept:
    作用:浏览器可以接受的媒体类型(MIME类型),
    例如:  Accept: text/html  代表浏览器可以接受服务器回发的类型为 text/html  也就是我们常说的html文档, 如果服务器无法返回text/html类型的数据,服务器应该返回一个406错误(non acceptable)。
    通配符 * 代表任意类型。例如  Accept: */*  代表浏览器可以处理所有类型,(一般浏览器发给服务器都是发这个)
    Accept-Encoding:
    作用: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate),(注意:这不是只字符编码);
    例如: Accept-Encoding: gzip, deflate。Server能够向支持gzip/deflate的浏览器返回经gzip或者deflate编码的HTML页面。 许多情形下这可以减少5到10倍的下载时间,也节省带宽。
    Accept-Language:
    作用: 浏览器申明自己接收的语言。
    语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等;
    例如: Accept-Language:zh-cn 。如果请求消息中没有设置这个报头域,服务器假定客户端对各种语言都可以接受。
    User-Agent:
    作用:告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本.
    我们上网登陆论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往让很多人感到很神奇,实际上, 服务器应用程序就是从User-Agent这个请求报头域中获取到这些信息User-Agent请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器。
    例如: User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)
    Accept-Charset:
    作用:浏览器申明自己接收的字符集,这就是本文前面介绍的各种字符集和字符编码,如gb2312,utf-8(通常我们说Charset包括了相应的字符编码方案);
    例如:Accept-Charset:iso-8859-1,gb2312.如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。
    Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中;
    Authorization请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含Authorization请求报头域的请求,要求服务器对其进行验证。
    Cookie/Login 头域
    Cookie:
    作用: 最重要的header, 将cookie的值发送给HTTP 服务器
    Entity头域
    Content-Length
    作用:发送给HTTP服务器数据的长度。即请求消息正文的长度;
    例如: Content-Length: 38
    Content-Type:
    作用:
    例如:Content-Type: application/x-www-form-urlencoded
    Miscellaneous 头域
    Referer:
    作用: 提供了Request的上下文信息的服务器,告诉服务器我是从哪个链接过来的,比如从我主页上链接到一个朋友那里, 他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问    他的网站。
    例如: Referer:http://translate.google.cn/?hl=zh-cn&tab=wT
    Cache 头域
    If-Modified-Since:
    作用: 把浏览器端缓存页面的最后修改时间发送到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行对比。如果时间一致,那么返回304,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中。

    例如:If-Modified-Since: Thu, 09 Feb 2012 09:07:57 GMT。
    If-None-Match:
    作用: If-None-Match和ETag一起工作,工作原理是在HTTP Response中添加ETag信息。 当用户再次请求该资源时,将在HTTP Request 中加入If-None-Match信息(ETag的值)。如果服务器验证资源的ETag没有改变(该资源没有更新),将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag.  使用这样的机制将提高网站的性能
    例如: If-None-Match: "03f2b33c0bfcc1:0"



    Pragma:
    作用: 防止页面被缓存, 在HTTP/1.1版本中,它和Cache-Control:no-cache作用一模一样
    Pargma只有一个用法, 例如: Pragma: no-cache
    注意: 在HTTP/1.0版本中,只实现了Pragema:no-cache, 没有实现Cache-Control
    Cache-Control:
    作用: 这个是非常重要的规则。 这个用来指定Response-Request遵循的缓存机制。各个指令含义如下
    Cache-Control:Public   可以被任何缓存所缓存()
    Cache-Control:Private     内容只缓存到私有缓存中
    Cache-Control:no-cache  所有内容都不会被缓存

    2. HTTP响应格式     
          在接收和解释请求消息后,服务器会返回一个 HTTP 响应消息。与 HTTP 请求类似,HTTP 响应也是由三个部分组成,分别是:状态行、消息报头和响应正文。如:
    HTTP/1.1 200 OK
    Date: Sun, 17 Mar 2013 08:12:54 GMT
    Server: Apache/2.2.8 (Win32) PHP/5.2.5
    X-Powered-By: PHP/5.2.5
    Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
    Pragma: no-cache
    Content-Length: 4393
    Keep-Alive: timeout=5, max=100
    Connection: Keep-Alive
    Content-Type: text/html; charset=utf-8
    <html>
    <head>
    <title>HTTP响应示例<title>
    </head>
    <body>
    Hello HTTP!
    </body>
    </html>


    1、状态行
    状态行由协议版本、数字形式的状态代码,及相应的状态描述组成,各元素之间以空格分隔,结尾时回车换行符,格式如下:
    HTTP-Version Status-Code Reason-Phrase CRLF
    HTTP-Version 表示服务器 HTTP 协议的版本,Status-Code 表示服务器发回的响应代码,Reason-Phrase 表示状态代码的文本描述,CRLF 表示回车换行。例如:
    HTTP/1.1 200 OK (CRLF)
    状态代码与状态描述
        状态代码由 3 位数字组成, 表示请求是否被理解或被满足,状态描述给出了关于状态码的简短的文字描述。状态码的第一个数字定义了响应类别,后面两位数字没有具体分类。第一个数字有 5 种取值,如下所示。
    •     1xx:指示信息——表示请求已经接受,继续处理
    •     2xx:成功——表示请求已经被成功接收、理解、接受。
    •     3xx:重定向——要完成请求必须进行更进一步的操作
    •     4xx:客户端错误——请求有语法错误或请求无法实现
    •     5xx:服务器端错误——服务器未能实现合法的请求。
    •     常见状态代码、状态描述、说明:
    1xx 表示临时响应并需要请求者继续执行操作的状态代码。
    •     代码 说明
    •     100 (继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
    •     101 (切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。
    •     2xx (成功)
    •     表示成功处理了请求的状态代码。
    •     代码 说明
    •     200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
    •     201 (已创建) 请求成功并且服务器创建了新的资源。
    •     202 (已接受) 服务器已接受请求,但尚未处理。
    •     203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。
    •     204 (无内容) 服务器成功处理了请求,但没有返回任何内容。
    •     205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。
    •     206 (部分内容) 服务器成功处理了部分 GET 请求。
    •     3xx (重定向)
    •     表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
    •     代码 说明
    •     300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
    •     301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
    •     302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
    •     303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
    •     304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
    •     305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
    •     307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
    •     4xx(请求错误)
    •     这些状态代码表示请求可能出错,妨碍了服务器的处理。
    •     代码 说明
    •     400 (错误请求) 服务器不理解请求的语法。
    •     401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
    •     403 (禁止) 服务器拒绝请求。
    •     404 (未找到) 服务器找不到请求的网页。
    •     405 (方法禁用) 禁用请求中指定的方法。
    •     406 (不接受) 无法使用请求的内容特性响应请求的网页。
    •     407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
    •     408 (请求超时) 服务器等候请求时发生超时。
    •     409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
    •     410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。
    •     411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。
    •     412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。
    •     413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
    •     414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
    •     415 (不支持的媒体类型) 请求的格式不受请求页面的支持。
    •     416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。
    •     417 (未满足期望值) 服务器未满足"期望"请求标头字段的要求。
    •     5xx(服务器错误)
    •     这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。
    •     代码 说明
    •     500 (服务器内部错误) 服务器遇到错误,无法完成请求。
    •     501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
    •     502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
    •     503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
    •     504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
    •     505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。


    2、响应正文
    响应正文就是服务器返回的资源的内容,响应头和正文之间也必须用空行分隔。如:
    1.     <html> 
    2.     <head> 
    3.     <title>HTTP响应示例<title> 
    4.     </head> 
    5.     <body> 
    6.     Hello HTTP! 
    7.     </body> 
    8.     </html>


    3 、响应头信息
    HTTP最常见的响应头如下所示:
    Cache头域
    Date:
    作用:生成消息的具体时间和日期,即当前的GMT时间。
    例如: Date: Sun, 17 Mar 2013 08:12:54 GMT
    Expires:
    作用: 浏览器会在指定过期时间内使用本地缓存,指明应该在什么时候认为文档已经过期,从而不再缓存它。
    例如: Expires: Thu, 19 Nov 1981 08:52:00 GMT 
    Vary
    作用:
    例如: Vary: Accept-Encoding
    Cookie/Login 头域
    P3P
    作用: 用于跨域设置Cookie, 这样可以解决iframe跨域访问cookie的问题
    例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR
    Set-Cookie
    作用: 非常重要的header, 用于把cookie 发送到客户端浏览器, 每一个写入cookie都会生成一个Set-Cookie.
    例如: Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/
    Entity实体头域:
    实体内容的属性,包括实体信息类型,长度,压缩方法,最后一次修改时间,数据有效性等。
    ETag:
    作用:  和If-None-Match 配合使用。 (实例请看上节中If-None-Match的实例)
    例如: ETag: "03f2b33c0bfcc1:0"
    Last-Modified:
    作用: 用于指示资源的最后修改日期和时间。(实例请看上节的If-Modified-Since的实例)
    例如: Last-Modified: Wed, 21 Dec 2011 09:09:10 GMT
    Content-Type:
    作用:WEB服务器告诉浏览器自己响应的对象的类型和字符集,

    例如:
            Content-Type: text/html; charset=utf-8
      Content-Type:text/html;charset=GB2312
      Content-Type: image/jpeg
    Content-Length:
    指明实体正文的长度,以字节方式存储的十进制数字来表示
    在数据下行的过程中,Content-Length的方式要预先在服务器中缓存所有数据,然后所有数据再一股脑儿地发给客户端。
      例如: Content-Length: 19847
    Content-Encoding:
    作用:文档的编码(Encode)方法。一般是压缩方式。
    WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。利用gzip压缩文档能够显著地减少HTML文档的下载时间。
    例如:Content-Encoding:gzip
    Content-Language:
    作用: WEB服务器告诉浏览器自己响应的对象的语言者
    例如: Content-Language:da
    Miscellaneous 头域
    Server:
    作用:指明HTTP服务器的软件信息
    例如:Apache/2.2.8 (Win32) PHP/5.2.5
    X-Powered-By:
    作用:表示网站是用什么技术开发的
    例如: X-Powered-By: PHP/5.2.5
    Transport头域
    Connection:
    例如: Connection: keep-alive   当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接
    例如:  Connection: close  代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。
    Location头域
    Location:
    作用: 用于重定向一个新的位置, 包含新的URL地址
    实例请看304状态实例
    HTTP协议是无状态的和Connection: keep-alive的区别
      无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。从另一方面讲,打开一个服务器上的网页和你之前打开这个服务器上的网页之间没有任何联系。
      HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接)。
      从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。
    Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。
    3. 浏览器缓存     
           浏览器缓存:包括页面html缓存和图片js,css等资源的缓存。如下图,浏览器缓存是基于把页面信息保存到用户本地电脑硬盘里。
    1、缓存的优点:
         1)服务器响应更快:因为请求从缓存服务器(离客户端更近)而不是源服务器被相应,这个过程耗时更少,让服务器看上去响应更快。
         2)减少网络带宽消耗:当副本被重用时会减低客户端的带宽消耗;客户可以节省带宽费用,控制带宽的需求的增长并更易于管理。
    1、缓存工作原理
           页面缓存状态是由http header决定的,一个浏览器请求信息,一个是服务器响应信息。主要包括Pragma: no-cache、Cache-Control、 Expires、 Last-Modified、If-Modified-Since。其中Pragma: no-cache由HTTP/1.0规定,Cache-Control由HTTP/1.1规定。
           工作原理图:
    从图中我们可以看到原理主要分三步:
    1.     第一次请求:浏览器通过http的header报头,附带Expires,Cache-Control,Last-Modified/Etag向服务器请求,此时服务器记录第一次请求的Last-Modified/Etag                 
    2.     再次请求:当浏览器再次请求的时候,请求头附带Expires,Cache-Control,If-Modified-Since/Etag向服务器请求
    3.     服务器根据第一次记录的Last-Modified/Etag和再次请求的If-Modified-Since/Etag做对比,判断是否需要更新,服务器通过这两个头判断本地资源未发生变化,客 户端不需要重新下载,返回304响应。常见流程如下图所示:

    与缓存相关的HTTP扩展消息头
        Expires:设置页面过期时间,格林威治时间GMT
        Cache-Control:更细致的控制缓存的内容
        Last-Modified:请求对象最后一次的修改时间 用来判断缓存是否过期 通常由文件的时间信息产生
        ETag:响应中资源的校验值,在服务器上某个时段是唯一标识的。ETag是一个可以 与Web资源关联的记号(token),和Last-Modified功能才不多,也是一个标识符,一般和Last-Modified一起使用,加强服务器判断的准确度。
        Date:服务器的时间
        If-Modified-Since:客户端存取的该资源最后一次修改的时间,用来和服务器端的Last-Modified做比较
        If-None-Match:客户端存取的该资源的检验值,同ETag。
    Cache-Control的主要参数
    Cache-Control: private/public Public 响应会被缓存,并且在多用户间共享。 Private 响应只能够作为私有的缓存,不能再用户间共享。
    Cache-Control: no-cache:不进行缓存
    Cache-Control: max-age=x:缓存时间 以秒为单位
    Cache-Control: must-revalidate:如果页面是过期的 则去服务器进行获取。
    2、关于图片,css,js,flash的缓存
    这个主要通过服务器的配置来实现这个技术,如果使用apache服务器的话,可以使用mod_expires模块来实现:
    编译mod_expires模块:
    cd  /root/httpd-2.2.3/modules/metadata
    /usr/local/apache/bin/apxs -i -a -c mod_expires.c //编译
    编辑httpd.conf配置:添加下面内容
    <IfModule mod_expires.c>
    ExpiresActive on
    ExpiresDefault "access plus 1 month"
    ExpiresByType text/html "access plus 1 months"
    ExpiresByType text/css "access plus 1 months"
    ExpiresByType image/gif "access plus 1 months"
    ExpiresByType image/jpeg "access plus 1 months"
    ExpiresByType image/jpg "access plus 1 months"
    ExpiresByType image/png "access plus 1 months"
    EXpiresByType application/x-shockwave-flash "access plus 1 months"
    EXpiresByType application/x-javascript      "access plus 1 months"
    #ExpiresByType video/x-flv "access plus 1 months"
    </IfModule>
    解释:第一句--开启服务
    第二句--默认时间是一个月
    在下面是关于各种类型的资源的缓存时间设置
    http1.0和http1.1的区别和联系
    1. Persistent Connection持久连接
    在HTTP1.0中,每对Request/Response都使用一个新的连接。
    HTTP 1.1则支持持久连接Persistent Connection, 并且默认使用persistent  connection. 在同一个tcp的连接中可以传送多个HTTP请求和响应. 多个请求和响应可以重叠,多个请求和响应可以同时进行. 更加多的请求头和响应头(比如HTTP1.0没有host的字段).
            HTTP 1.1的持续连接,也需要增加新的请求头来帮助实现,例如,Connection请求头的值为Keep-Alive时,客户端通知服务器返回本次请求结果后保持连接;Connection请求头的值为close时,客户端通知服务器返回本次请求结果后关闭连接。HTTP 1.1还提供了与身份认证、状态管理和Cache缓存等机制相关的请求头和响应头。
            HTTP 1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求。此外,由于大多数网页的流量都比较小,一次TCP连接很少能通过slow-start区,不利于提高带宽利用率。
            在1.0时的会话方式:
           1. 建立连接
           2. 发出请求信息
           3. 回送响应信息
           4. 关掉连接
           小结:浏览器和web服务器连接很短,每次连接只处理一个请求和响应。对每一个页的请求,浏览器与web服务器都要建立一次单独的连接.浏览器没有 关掉前,连接就断开了.浏览器和服务器之间的通信是完全独立分开的请求和响应对.因为这样没法断点浏览器是否断开,没法做连接状态控制。建立和关掉连接会很占用连接时间.
          在一个网页中,在http头中的Connection中有多少个close的头,就相当有多少个http的连接.
      HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。例如:一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接。
           HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。
           在HTTP/1.0中,要建立长连接,可以在请求消息中包含Connection: Keep-Alive头域,如果服务器愿意维持这条连接,在响应消息中也会包含一个Connection: Keep-Alive的头域。同时,可以加入一些指令描述该长连接的属性,如max,timeout等。
           事实上,Connection头域可以携带三种不同类型的符号:
           1、一个包含若干个头域名的列表,声明仅限于一次hop连接的头域信息;
           2、任意值,本次连接的非标准选项,如Keep-Alive等;
            3、close值,表示消息传送完成之后关闭长连接;
            客户端和源服务器之间的消息传递可能要经过很多中间节点的转发,这是一种逐跳传递(hop-by-hop)。HTTP/1.1相应地引入了hop-by-hop头域,这种头域仅作用于一次hop,而非整个传递路径。每一个中间节点(如Proxy,Gateway)接收到的消息中如果包含Connection头域,会查找Connection头域中的一个头域名列表,并在将消息转发给下一个节点之前先删除消息中这些头域。
            通常,HTTP/1.0的Proxy不支持Connection头域,为了不让它们转发可能误导接收者的头域,协议规定所有出现在Connection头域中的头域名都将被忽略。
    2. Host域
           在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。
    HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。此外,服务器应该接受以绝对路径标记的资源请求。
            HTTP1.1在Request消息头里头多了一个Host域,比如:
           GET /pub/WWW/TheProject.html HTTP/1.1
           Host: www.w3.org
           HTTP1.0则没有这个域。
           可能HTTP1.0的时候认为,建立TCP连接的时候已经指定了IP地址,这个IP地址上只有一个host。
           由于HTTP 1.0不支持Host请求头字段,WEB浏览器无法使用主机头名来明确表示要访问服务器上的哪个WEB站点,这样就无法使用WEB服务器在同一个IP地址和端口号上配置多个虚拟WEB站点。在HTTP 1.1中增加Host请求头字段后,WEB浏览器可以使用主机头名来明确表示要访问服务器上的哪个WEB站点,这才实现了在一台WEB服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟WEB站点。
    3. date/timestamp (日期时间戳)
    (接收方向)
    无论是HTTP1.0还是HTTP1.1,都要能解析下面三种date/time stamp:
          Sun, 06 Nov 1994 08:49:37GMT  ; RFC 822, updated by RFC 1123
          Sunday, 06-Nov-94 08:49:37GMT ; RFC 850, obsoleted by RFC 1036
          Sun Nov  6 08:49:371994       ; ANSI C's asctime() format
    (发送方向)
       HTTP1.0要求不能生成第三种asctime格式的date/time stamp;
        HTTP1.1则要求只生成RFC 1123(第一种)格式的date/time stamp。
    4. Transfer Codings
    HTTP1.1支持chunked transfer,所以可以有Transfer-Encoding头部域:
    Transfer-Encoding:chunked
    HTTP1.0则没有。
    HTTP消息中可以包含任意长度的实体,通常它们使用Content-Length来给出消息结束标志。但是,对于很多动态产生的响应,只能通过缓冲完整的消息来判断消息的大小,但这样做会加大延迟。如果不使用长连接,还可以通过连接关闭的信号来判定一个消息的结束。
    HTTP/1.1中引入了Chunked transfer-coding来解决上面这个问题,发送方将消息分割成若干个任意大小的数据块,每个数据块在发送时都会附上块的长度,最后用一个零长度的块作为消息结束的标志。这种方法允许发送方只缓冲消息的一个片段,避免缓冲整个消息带来的过载。
    在HTTP/1.0中,有一个Content-MD5的头域,要计算这个头域需要发送方缓冲完整个消息后才能进行。而HTTP/1.1中,采用chunked分块传递的消息在最后一个块(零长度)结束之后会再传递一个拖尾(trailer),它包含一个或多个头域,这些头域是发送方在传递完所有块之后再计算出值的。发送方会在消息中包含一个Trailer头域告诉接收方这个拖尾的存在。
    5. Quality Values
    HTTP1.1多了个qvalue域:
          qvalue         = ( "0" ["." 0*3DIGIT ] )
                         | ( "1" [ "." 0*3("0") ] )
    6. Entity Tags
    用于Cache。
    7. Range 和 Content-Range(节约优化)
           HTTP1.1支持传送内容的一部分。比方说,当客户端已经有内容的一部分,为了节省带宽,可以只向服务器请求一部分。
            HTTP/1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了。例如,客户端只需要显示一个文档的部分内容,又比如下载大文件时需要支持断点续传功能,而不是在发生断连后不得不重新下载完整的包。
            HTTP/1.1中在请求消息中引入了range头域,它允许只请求资源的某个部分。在响应消息中Content-Range头域声明了返回的这部分对象的偏移值和长度。如果服务器相应地返回了对象所请求范围的内容,则响应码为206(Partial Content),它可以防止Cache将响应误以为是完整的一个对象。
           节省带宽资源的一个非常有效的做法就是压缩要传送的数据。Content-Encoding是对消息进行端到端(end-to-end)的编码,它可能是资源在服务器上保存的固有格式(如jpeg图片格式);在请求消息中加入Accept-Encoding头域,它可以告诉服务器客户端能够解码的编码方式。
           而Transfer-Encoding是逐段式(hop-by-hop)的编码,如Chunked编码。在请求消息中加入TE头域用来告诉服务器能够接收的transfer-coding方式,
    8. 100(Continue) Status(节约带宽)
           另外一种浪费带宽的情况是请求消息中如果包含比较大的实体内容,但不确定服务器是否能够接收该请求(如是否有权限),此时若贸然发出带实体的请求,如果被拒绝也会浪费带宽。
            HTTP/1.1加入了一个新的状态码100(Continue)。客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(Unauthorized);如果服务器接收此请求就回送响应码100,客户端就可以继续发送带实体的完整请求了。注意,HTTP/1.0的客户端不支持100响应码。但可以让客户端在请求消息中加入Expect头域,并将它的值设置为100-continue。
          100 (Continue) 状态代码的使用,允许客户端在发request消息body之前先用request header试探一下server,看server要不要接收request body,再决定要不要发request body。
    客户端在Request头部中包含
    Expect: 100-continue
    Server看到之后呢如果回100 (Continue) 这个状态代码,客户端就继续发requestbody。
    这个是HTTP1.1才有的。
    9. Request method
         HTTP1.1增加了OPTIONS,PUT, DELETE, TRACE, CONNECT这些Request方法.
          Method   ="OPTIONS"               ;Section 9.2
                         |"GET"                   ; Section 9.3
                         |"HEAD"                  ; Section 9.4
                         |"POST"                  ; Section 9.5
                         | "PUT"                   ;Section 9.6
                         | "DELETE"                ;Section 9.7
                         |"TRACE"                 ; Section 9.8
                         | "CONNECT"               ;Section 9.9
                         | extension-method
           extension-method =token
    10. Status code
      HTTP1.1 增加的新的status code:
    (HTTP1.0没有定义任何具体的1xx status code, HTTP1.1有2个)
    100 Continue
    101 Switching Protocols
    203 Non-Authoritative Information
    205 Reset Content
    206 Partial Content
    302 Found (在HTTP1.0中有个 302 Moved Temporarily)
    303 See Other
    305 Use Proxy
    307 Temporary Redirect
    405 Method Not Allowed
    406 Not Acceptable
    407 Proxy Authentication Required
    408 Request Timeout
    409 Conflict
    410 Gone
    411 Length Required
    412 Precondition Failed
    413 Request Entity Too Large
    414 Request-URI Too Long
    415 Unsupported Media Type
    416 Requested Range Not Satisfiable
    417 Expectation Failed
    504 Gateway Timeout
    505 HTTP Version Not Supported
    11. Cache (缓存)
           在HTTP/1.0中,使用Expire头域来判断资源的fresh或stale,并使用条件请求(conditional request)来判断资源是否仍有效。例如,cache服务器通过If-Modified-Since头域向服务器验证资源的Last-Modefied头域是否有更新,源服务器可能返回304(Not Modified),则表明该对象仍有效;也可能返回200(OK)替换请求的Cache对象。
    此外,HTTP/1.0中还定义了Pragma:no-cache头域,客户端使用该头域说明请求资源不能从cache中获取,而必须回源获取。
    HTTP/1.1在1.0的基础上加入了一些cache的新特性,当缓存对象的Age超过Expire时变为stale对象,cache不需要直接抛弃stale对象,而是与源服务器进行重新激活(revalidation)。
    HTTP/1.0中,If-Modified-Since头域使用的是绝对时间戳,精确到秒,但使用绝对时间会带来不同机器上的时钟同步问题。而HTTP/1.1中引入了一个ETag头域用于重激活机制,它的值entity tag可以用来唯一的描述一个资源。请求消息中可以使用If-None-Match头域来匹配资源的entitytag是否有变化。
    为了使caching机制更加灵活,HTTP/1.1增加了Cache-Control头域(请求消息和响应消息都可使用),它支持一个可扩展的指令子集:例如max-age指令支持相对时间戳;private和no-store指令禁止对象被缓存;no-transform阻止Proxy进行任何改变响应的行为。
    Cache使用关键字索引在磁盘中缓存的对象,在HTTP/1.0中使用资源的URL作为关键字。但可能存在不同的资源基于同一个URL的情况,要区别它们还需要客户端提供更多的信息,如Accept-Language和Accept-Charset头域。为了支持这种内容协商机制(content negotiation mechanism),HTTP/1.1在响应消息中引入了Vary头域,该头域列出了请求消息中需要包含哪些头域用于内容协商。
    依据:
    rfc2616Hypertext Transfer Protocol -- HTTP-1.1.txt
    rfc1945Hypertext Transfer Protocol -- HTTP 1.0.txt
    HTTP 1.1持久连接的好处
            一个WEB站点每天可能要接收到上百万的用户请求,为了提高系统的效率,HTTP 1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求。但是,这也造成了一些性能上的缺陷,例如,一个包含有许多图像的网页文件中并没有包含真正的图像数据内容,而只是指明了这些图像的URL地址,当WEB浏览器访问这个网页文件时,浏览器首先要发出针对该网页文件的请求,当浏览器解析WEB服务器返回的该网页文档中的HTML内容时,发现其中的<img>图像标签后,浏览器将根据<img>标签中的src属性所指定的URL地址再次向服务器发出下载图像数据的请求,如图3.3所示。
    显然,访问一个包含有许多图像的网页文件的整个过程包含了多次请求和响应,每次请求和响应都需要建立一个单独的连接,每次连接只是传输一个文档和图像,上一 次和下一次请求完全分离。即使图像文件都很小,但是客户端和服务器端每次建立和关闭连接却是一个相对比较费时的过程,并且会严重影响客户机和服务器的性 能。当一个网页文件中包含Applet,JavaScript文件,CSS文件等内容时,也会出现类似上述的情况。
            为了克服HTTP 1.0的这个缺陷,HTTP1.1支持持久连接,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接。HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。基于HTTP 1.1协议的客户机与服务器的信息交换过程,如图3.4所示。
            可见,HTTP 1.1在继承了HTTP 1.0优点的基础上,也克服了HTTP 1.0的性能问题。不仅如此,HTTP 1.1还通过增加更多的请求头和响应头来改进和扩充HTTP1.0的功能。例如,由于HTTP 1.0不支持Host请求头字段,WEB浏览器无法使用主机头名来明确表示要访问服务器上的哪个WEB站点,这样就无法使用WEB服务器在同一个IP地址和端口号上配置多个虚拟WEB站点。在HTTP 1.1中增加Host请求头字段后,WEB浏览器可以使用主机头名来明确表示要访问服务器上的哪个WEB站点,这才实现了在一台WEB服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟WEB站点。HTTP 1.1的持续连接,也需要增加新的请求头来帮助实现,例如,Connection请求头的值为Keep-Alive时,客户端通知服务器返回本次请求结果后保持连接;Connection请求头的值为close时,客户端通知服务器返回本次请求结果后关闭连接。HTTP 1.1还提供了与身份认证、状态管理和Cache缓存等机制相关的请求头和响应头。
    参考来源:
    HTTP详解(1)-工作原理
    HTTP详解(2)-请求、响应、缓存
    HTTP详解(3)-http1.0 和http1.1 区别
    (2)TCP/UDP协议
    1.TCP和UDP区别
                           TCP        UDP
    是否连接     面向连接     面向非连接
    传输可靠性     可靠的     不可靠的
    应用场合     传输大量的数据     少量数据
    速度              慢                       快

    OSI 和 TCP/IP 模型在传输层定义两种传输协议:TCP(传输控制协议)和 UDP(用户数据报协议)。
    UDP
        UDP 与 TCP 的主要区别在于 UDP 不一定提供可靠的数据传输。事实上,该协议不能保证数据准确无误地到达目的地。UDP 在许多方面非常有效。当某个程序的目标是尽快地传输尽可能多的信息时(其中任意给定数据的重要性相对较低),可使用 UDP。ICQ 短消息使用 UDP 协议发送消息。
        许多程序将使用单独的TCP连接和单独的UDP连接。重要的状态信息随可靠的TCP连接发送,而主数据流通过UDP发送。
    TCP
        TCP的目的是提供可靠的数据传输,并在相互进行通信的设备或服务之间保持一个虚拟连接。TCP在数据包接收无序、丢失或在交付期间被破坏时,负责数据恢复。它通过为其发送的每个数据包提供一个序号来完成此恢复。记住,较低的网络层会将每个数据包视为一个独立的单元,因此,数据包可以沿完全不同的路径发送,即使它们都是同一消息的组成部分。这种路由与网络层处理分段和重新组装数据包的方式非常相似,只是级别更高而已。
        为确保正确地接收数据,TCP要求在目标计算机成功收到数据时发回一个确认(即 ACK)。如果在某个时限内未收到相应的 ACK,将重新传送数据包。如果网络拥塞,这种重新传送将导致发送的数据包重复。但是,接收计算机可使用数据包的序号来确定它是否为重复数据包,并在必要时丢弃它。
    TCP与UDP的选择
        如果比较UDP包和TCP包的结构,很明显UDP包不具备TCP包复杂的可靠性与控制机制。与TCP协议相同,UDP的源端口数和目的端口数也都支持一台主机上的多个应用。一个16位的UDP包包含了一个字节长的头部和数据的长度,校验码域使其可以进行整体校验。(许多应用只支持UDP,如:多媒体数据流,不产生任何额外的数据,即使知道有破坏的包也不进行重发。)
        很明显,当数据传输的性能必须让位于数据传输的完整性、可控制性和可靠性时,TCP协议是当然的选择。当强调传输性能而不是传输的完整性时,如:音频和多媒体应用,UDP是最好的选择。在数据传输时间很短,以至于此前的连接过程成为整个流量主体的情况下,UDP也是一个好的选择,如:DNS交换。把SNMP建立在UDP上的部分原因是设计者认为当发生网络阻塞时,UDP较低的开销使其有更好的机会去传送管理数据。TCP丰富的功能有时会导致不可预料的性能低下,但是我们相信在不远的将来,TCP可靠的点对点连接将会用于绝大多数的网络应用。
    TCP协议和UDP协议特性区别总结:
    1. TCP协议在传送数据段的时候要给段标号;UDP协议不需要
    2. TCP协议可靠;UDP协议不可靠
    3. TCP协议是面向连接;UDP协议采用无连接
    4. TCP协议负载较高,采用虚电路;UDP采用无连接
    5. TCP协议的发送方要确认接收方是否收到数据段(3次握手协议)
    6. TCP协议采用窗口技术和流控制

    2. TCP、UDP详解
    1、传输层存在的必要性
    由于网络层的分组传输是不可靠的,无法了解数据到达终点的时间,无法了解数据未达终点的状态。因此有必要增强网络层提供服务的服务质量。
    2、引入传输层的原因
    面向连接的传输服务与面向连接的网络服务类似,都分为建立连接、数据传输、释放连接三个阶段;编址、寻址、流控制也是类似的。无连接的传输服务与无连接的网络服务也非常类似。一个很显然的问题:既然传输层的服务与网络层的服务如此相似,那么为什么我们还要两个独立的层呢?
    原因在于:传输层的代码完全运行在用户的机器上,但是网络层主要运行在由承运商控制的路由器上。试想以下几种情况?
    ①网络层提供的服务不够用;
    ②频繁的丢失分组;
    ③路由器时常崩溃。
    用户在网络层上并没有真正的控制权,所以他们不可能用最好的路由器或者在数据链路层上用更好的错误处理机制来解决服务太差的问题。唯一的可能是在网络层之上的另一层中提高服务质量。这就是传输层存在的必要性。
    传输层的重要性:不仅仅是另外一层,它是整个协议层次的核心所在。如果没有传输层,那么分层协议的整个概念将变得没有意义。
    传输层的任务:在源机器和目标机器之间提供可靠的、性价比合理的数据传输服务,并且与当前使用的物理网络完全独立。
    3、传输层的功能
    数据传送,不关心数据含义,进程间通信。
    弥补高层(上3层)要求与网络层(基于下3层)数据传送服务质量间的差异(差错率、差错恢复能力、吞吐率、延时、费用等),对高层屏蔽网络层的服务的差异,提供稳定和一致的界面。
    4、传输层协议与网络层协议的主要区别
    网络层(IP层)提供点到点的连接即提供主机之间的逻辑通信,传输层提供端到端的连接——提供进程之间的逻辑通信。
    5、传输层的用途
    传输层将数据分段,并进行必要的控制,以便将这些片段重组成各种通信流。在此过程中,传输层主要负责:
    ①跟踪源主机和目的主机上应用程序间的每次通信;
    ②将数据分段,并管理每个片段;
    ③将分段数据重组为应用程序数据流;
    ④标识不同的应用程序。
    6、端口号的概念
    运行在计算机中的进程是用进程标识符来标志的。运行在应用层的各种应用进程却不应当让计算机操作系统指派它的进程标识符。这是因为在因特网上使用的计算机的操作系统种类很多,而不同的操作系统又使用不同格式的进程标识符。为了使运行不同操作系统的计算机的应用进程能够互相通信,就必须用统一的方法对TCP/IP体系的应用进程进行标志。解决这个问题的方法就是在运输层使用协议端口号(protocol port number),或通常简称为端口(port)。虽然通信的终点是应用进程,但我们可以把端口想象是通信的终点,因为我们只要把要传送的报文交到目的主机的某一个合适的目的端口,剩下的工作(即最后交付目的进程)就由 TCP来完成。

    7、传输层的主要协议
    TCP/ IP传输层的两个主要协议都是因特网的重要标准,传输控制协议TCP(Transmission Control Protocol)[RFC 768]、用户数据报协议UDP(User Datagram Protocol)[RFC 793]。
    传输层的数据流要在网络端点之间建立逻辑连接。如果使用UDP,传输层的首要任务是将数据从源设备传输到目的设备。如果使用TCP,传输层主要通过滑动窗口来提供端到端控制,以及利用确认序列号和确认信息提供可靠性。传输层定义主机应用程序之间端到端的连接。
    8、TCP&UDP的比较
    TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。
    UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。
    问题1:什么是面向连接、面向无连接?
    面向连接举例:两个人之间通过电话进行通信。
    面向无连接举例:邮政服务,用户把信函放在邮件中期待邮政处理流程来传递邮政包裹。显然,不可达代表不可靠。
    从程序实现的角度解析面向连接、面向无连接如下:
    TCP面向连接,UDP面向无连接(在默认的阻塞模式下):
    在TCP协议中,当客户端退出程序或断开连接时,TCP协议的recv函数会立即返回不再阻塞,因为服务端自己知道客户端已经退出或断开连接,证明它是面向连接的;
    而在UDP协议中,recvfrom这个接收函数将会始终保持阻塞,因为服务端自己不知道客户端已经退出或断开连接,证明它是面向无连接的)。

    从上图也能清晰的看出,TCP通信需要服务器端侦听listen、接收客户端连接请求accept,等待客户端connect建立连接后才能进行数据包的收发(recv/send)工作。而UDP则服务器和客户端的概念不明显,服务器端即接收端需要绑定端口,等待客户端的数据的到来。后续便可以进行数据的收发(recvfrom/sendto)工作。

    问题2:什么是面向字节流、面向报文?
    面向字节流:虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。
    面向报文:面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片,降低效率。若太短,会是IP太小。(谢希仁,第五版。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给UDP多长的报文,UDP就照样发送),即一次发送一个报文)。


    问题3:在默认的阻塞模式下,为什么说TCP无边界,UDP有边界?
    对于TCP协议,客户端连续发送数据,只要服务端的这个函数的缓冲区足够大,会一次性接收过来,即客户端是分好几次发过来,是有边界的,而服务端却一次性接收过来,所以证明是无边界的;
    而对于UDP协议,客户端连续发送数据,即使服务端的这个函数的缓冲区足够大,也只会一次一次的接收,发送多少次接收多少次,即客户端分几次发送过来,服务端就必须按几次接收,从而证明,这种UDP的通讯模式是有边界的。
    问题4:UDP 如何发送大量的数据?如何处理分包?
    用 updclient 一次不能发送太大的数据量,不然就会报错:一个在数据报套接字上发送的消息大于内部消息缓冲器或其他一些网络限制,或该用户用于接收数据报的缓冲器比数据报小。但不知道一次到底能发多少字节?如果把一个大的字节数组拆分成若干个字节数组发送,那么接收时如何判断和处理呢?
    答:方法很简单:
    1、在客户端将你要发送的内容(文件什么的都可以)分块,每块内容进行编号,然后发送;
    2、服务端在接收到你的分块数据以后,根据你的客户端数据内容的编号重新组装;
    3、一般我们在发送数据的时候,尽量采用比较小的数据块的方式(我的都没有超过1024的),数据块太大的话容易出现发送和接收的数据时间长,匹配出问题。
    问题5.UDP发包的问题
    问:udp发送两次数据,第一次 100字节,第二次200字节,接包方一次recvfrom( 1000 ),收到是 100,还是200,还是300?
    答:UDP是数据报文协议,是以数据包方式,所以每次可以接收100,200,在理想情况下,第一次是无论recvfrom多少都是接收到100。当然,可能由于网络原因,第二个包先到的话,有可能是200了。对可能会由于网络原因乱序,所以可能先收到200,所以自定义的udp协议包头里都要加上一个序列号,标识发送与收包对应。
    问题6.TCP的发包问题
    问:同样如果换成tcp,第一次发送 100字节,第二次发送200字节,recv( 1000 )会接收到多少?
    答:tcp是流协议,所以recv( 1000 ),会收到300 tcp自己处理好了重传,保证数据包的完整性
    问题7.有分片的情况下如下处理
    问:如果MTU是1500,使用UDP发送 2000,那么recvfrom(2000)是收到1500,还是2000?
    答:还是接收2000,数据分片由ip层处理了,放到udp还是一个完整的包。接收到的包是由路由路径上最少的MTU来分片,注意转到UDP已经在是组装好的(组装出错的包会经crc校验出错而丢弃),是一个完整的数据包。
    问题8.分片后的处理
    问:如果500那个片丢了怎么办?udp又没有重传
    答:udp里有个crc检验,如果包不完整就会丢弃,也不会通知是否接收成功,所以UDP是不可靠的传输协议,而且TCP不存在这个问题,有自己的重传机制。在内网来说,UDP基本不会有丢包,可靠性还是有保障。当然如果是要求有时序性和高可靠性,还是走TCP,不然就要自己提供重传和乱序处理( UDP内网发包处理量可以达7M~10M/s )
    问题9.不同连接到同一个端口的包处理
    问:TCP
       A -> C发100
       B -> C发200
       AB同时同一端口
       C recv(1000) ,会收到多少?
    答:A与C是一个tcp连接,B与C又是另一个tcp连接,所以不同socket,所以分开处理。每个socket有自己的接收缓冲和发送缓冲
    问题10.什么是TCP粘包
    在应用开发过程中,基于TCP网络传输的应用程序有时会出现粘包现象(即发送方发送的若干包数据到接收方接收时粘成一包)。详细解释如下:由于TCP是流协议,对于一个socket的包,如发送 10AAAAABBBBB两次,由于网络原因第一次又分成两次发送, 10AAAAAB和BBBB,如果接包的时候先读取10(包长度)再读入后续数据,当接收得快,发送的慢时,就会出现先接收了 10AAAAAB,会解释错误 ,再接到BBBB10AAAAABBBBB,也解释错误的情况。这就是TCP的粘包。
    在网络传输应用中,通常需要在网络协议之上再自定义一个协议封装一下,简单做法就是在要发送的数据前面再加一个自定义的包头,包头中可以包含数据长度和其它一些信息,接收的时候先收包头,再根据包头中描述的数据长度来接收后面的数据。详细做法是:先接收包头,在包头里指定包体长度来接收。设置包头包尾的检查位(如群空间0x2开头,0x3结束来检查一个包是否完整)。对于TCP来说:1)不存在丢包,错包,所以不会出现数据出错 2)如果包头检测错误,即为非法或者请求,直接重置即可
    为了避免粘包现象,可采取以下几种措施。
    一是对于发送方引起的粘包现象,用户可通过编程设置来避免,TCP提供了强制数据立即传送的操作指令push,TCP软件收到该操作指令后,就立即将本段数据发送出去,而不必等待发送缓冲区满;
    二是对于接收方引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象;
    三是由接收方控制,将一包数据按结构字段,人为控制分多次接收,然后合并,通过这种手段来避免粘包。
    问题11.图解TCP的3次握手建立连接,4次握手释放连接?
    TCP是面向连接的协议。运输连接是用来传送TCP报文的。TCP传输连接的建立和释放是每一次面向连接的通信中必不可少的过程。因此,传输连接就由三个阶段,即:连接建立、数据传送和连接释放。
    这里的SYN=SYNchronization,SYN=1,ACK=0,表示连接请求报文段;同意建立连接则SYN=1,ACK=1,连接后所有的ACK=1。
    三次握手(three-way handshake)方案解决了由于网络层会丢失、存储和重复分组带来的问题。试想不进行三次握手可能出现的问题?
    如上图所示,如果仅仅是2次握手的话,可能出现的问题如下:
    Host A发送的数据包由于网络的原因,出现了滞留,即延时到达了HostB。此时,B以为HostA发来了请求,于是就向HostA发送确认报文,以建立连接。而HostA收到报文后,由于其没有向HostB发起建立连接的请求,因此不会理睬HostB的确认,也不会向HostB发送数据。而此时的B认为已经建立起连接了,就等待HostA发送的数据,导致HostB的资源白白浪费!
    连接释放:
    参考来源:TCP、UDP详解

  • 相关阅读:
    Android移动view动画问题
    GIT常用操作
    linux下mysql安装
    jdk安装
    linux下Tomcat安装
    猜测性能瓶颈
    MySQL没有远程连接权限设置
    linux下jmeter使用帮助
    BI的核心价值[转]
    BI与大数据
  • 原文地址:https://www.cnblogs.com/ryanlamp/p/7443112.html
Copyright © 2020-2023  润新知