• C# HTTP系列8 GET与POST对比说明


     HTTP协议,即超文本传输协议(Hypertext transfer protocol)。是一种详细规定了浏览器和万维网(WWW = World Wide Web)服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。

    超文本传输协议(HTTP)的设计目的是保证客户机与服务器之间的通信。

    HTTP 的工作方式是客户机与服务器之间的请求-应答协议。

    web 浏览器可能是客户端,而计算机上的网络应用程序也可能作为服务器端。

    举例:客户端(浏览器)向服务器提交 HTTP 请求;服务器向客户端返回响应。响应包含关于请求的状态信息以及可能被请求的内容。

    在客户机和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST。

    • GET - 从指定的资源请求数据。
    • POST - 向指定的资源提交要被处理的数据
    GET方法

    查询字符串(名称/值对)是在 GET 请求的 URL 中发送的

    /test/demo_form.asp.net?name1=value1&name2=value2

    在约定中,参数是写在 ? 后面,用 & 分割。

    解析报文的过程是通过获取 TCP 数据,用正则等工具从数据中获取 Header 和 Body,从而提取参数。

    比如header请求头中添加token,来验证用户是否登录等权限问题。

    也就是说,可以自己约定参数的写法,只要服务端能够解释出来就行,万变不离其宗。

    应用场景:

    可以看到有General 、Response Headers、Request Headers。

    有关 GET 请求的其他一些注释:

    • GET 请求可被缓存
    • GET 请求保留在浏览器历史记录中
    • GET 请求可被收藏为书签
    • GET 请求不应在处理敏感数据时使用
    • GET 请求有长度限制
    • GET 请求只应当用于取回数据
    POST方法

    查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的

    POST /test/demo_form.asp.net HTTP/1.1
    Host: baidu.com
    name1=value1&name2=value2

    应用场景:

    可以看到POST请求中多了Form Data(body中的一种表单请求类型)。

    • headers:主要存放cookie等其他信息
    • body:主要存放POST的一些数据,如username:xxx

    有关 POST 请求的其他一些注释:

    • POST 请求不会被缓存
    • POST 请求不会保留在浏览器历史记录中
    • POST 不能被收藏为书签
    • POST 请求对数据长度没有要求
    GET 与 POST 比较

    下面的表格比较了两种 HTTP 方法:GET 和 POST。

     GETPOST
    后退按钮/刷新 无害 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。
    书签 可收藏为书签 不可收藏为书签
    缓存 能被缓存 不能缓存
    编码类型 application/x-www-form-urlencoded application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。
    历史 参数保留在浏览器历史中。 参数不会保存在浏览器历史中。
    对数据长度的限制 是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 无限制。
    对数据类型的限制 只允许 ASCII 字符。 没有限制。也允许二进制数据。
    安全性

    与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。

    在发送密码或其他敏感信息时绝不要使用 GET !

    POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。
    可见性 数据在 URL 中对所有人都是可见的。 数据不会显示在 URL 中。
     

    HTTP请求方法

    HTTP请求,最初设定了八种方法。这八种方法本质上没有任何区别。只是让请求更加有语义而已。

    下面的表格列出了其他一些 HTTP 请求方法。

    方法描述
    OPTIONS 返回服务器支持的 HTTP 请求方法。
    GET 向服务器获取指定资源。参数放在URL后面。
    HEAD 与 GET 相同,但只返回 HTTP 报头,不返回文档主体。
    POST 向服务器提交数据,数据放在请求体里。
    PUT

    上传指定的 URI 表示。

    与POST相似,只是具有幂等特性,一般用于更新。

    DELETE 删除服务器上的指定资源。
    TRACE 回显服务器端收到的请求,测试的时候会用到这个。
    CONNECT 把请求连接转换到透明的 TCP/IP 通道。
     
    GET 与 POST 本质区别
    从标准上来看,GET 和 POST 的区别如下:
    • GET 用于获取信息,是无副作用的,是幂等的,且可缓存;
    • POST 用于修改服务器上的数据,有副作用,非幂等,不可缓存。

    从请求报文上来看,GET、POST的区别如下:

    GET 和 POST 只是 HTTP 协议中两种请求方式(异曲同工),而 HTTP 协议是基于 TCP/IP 的应用层协议,无论 GET 还是 POST,用的都是同一个传输层协议,所以在传输上,没有任何区别。

    如果你要给GET加上request body,技术上是完全行的通的。

    如果你要给给POST带上url参数,技术上也是完全行的通的。

    但是尽量不要这么做,请按照 GET 与 POST 的标准要求去传递请求参数。

    在万维网世界中,TCP就像汽车,我们用TCP来运输数据,它很可靠,从来不会发生丢件少件的现象。但是如果路上跑的全是看起来一模一样的汽车,那这个世界看起来是一团混乱,送急件的汽车可能被前面满载货物的汽车拦堵在路上,整个交通系统一定会瘫痪。为了避免这种情况发生,交通规则HTTP诞生了。

    HTTP给汽车运输设定了好几个服务类别,有GET, POST, PUT, DELETE等等,HTTP规定,当执行GET请求的时候,要给汽车贴上GET的标签(设置method为GET),而且要求把传送的数据放在车顶上(url中)以方便记录。如果是POST请求,就要在车上贴上POST的标签,并把货物放在车厢里。当然,你也可以在GET的时候往车厢内偷偷藏点货物,但是这是很不光彩;也可以在POST的时候在车顶上也放一些数据,让人觉得傻乎乎的。HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。

    GET传参最大长度的理解
    HTTP 协议没有 Body 和 URL 的长度限制,对 URL 限制的大多是浏览器和服务器的原因。

    1、正解
    (1)HTTP 协议并未规定GET和POST的请求长度限制 ;
    (2)所谓的请求长度限制是由浏览器和web服务器决定和设置的。各种浏览器和web服务器的设定均不一样,这依赖于各个浏览器厂家的规定或者可以根据web服务器的处理能力来设定。IE 和 Safari 浏览器 限制 2k,Opera 限制4k,Firefox 限制 8k(非常老的版本 256byte),如果超出了最大长度,大部分的服务器直接截断,也有一些服务器会报414错误。

    2、各个浏览器和web服务器的最大长度总结 
    浏览器 
    (1)IE:IE浏览器(Microsoft Internet Explorer) 对url长度限制是2083(2K+53),超过这个限制,则自动截断(若是form提交则提交按钮不起作用)。 
    (2)Firefox:火狐浏览器的url长度限制为 65536字符,但实际上有效的URL最大长度不少于100,000个字符。 
    (3)Chrome:谷歌浏览的url长度限制超过8182个字符返回本文开头时列出的错误。 
    (4)Safari:Safari的url长度限制至少为 80 000 字符。 
    (5)Opera:Opera 浏览器的url长度限制为190 000 字符。Opera9 地址栏中输入190000字符时依然能正常编辑。 


    服务器 
    (1)Apache:Apache能接受url长度限制为8 192 字符 
    (2)IIS:Microsoft Internet Information Server(IIS)能接受url长度限制为16384个字符。这个是可以通过修改的(IIS7) 
                    configuration/system.webServer/security/requestFiltering/requestLimits@maxQueryStringsetting.

    服务器是因为处理长 URL 要消耗比较多的资源,为了性能和安全(防止恶意构造长 URL 来攻击)考虑,会给 URL 长度加限制。

    为什么GET比POST更快

    1、post请求包含更多的请求头 
         因为post需要在请求的body部分包含数据,所以会多了几个数据描述部分的首部字段(如:content-type),这其实是微乎其微的。

    2、最重要的一条,post在真正接收数据之前会先将请求头发送给服务器进行确认,然后才真正发送数据 
    post请求的过程: 
    (1)浏览器请求tcp连接(第一次握手); 
    (2)服务器答应进行tcp连接(第二次握手); 
    (3)浏览器确认,并发送post请求头(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送) ;
    (4)服务器返回100 Continue响应 ;
    (5)浏览器发送数据; 
    (6)服务器返回200 OK响应。

    get请求的过程: 
    (1)浏览器请求tcp连接(第一次握手); 
    (2)服务器答应进行tcp连接(第二次握手); 
    (3)浏览器确认,并发送get请求头和数据(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送) 
    (4)服务器返回200 OK响应 。
    也就是说,目测get的总耗是post的2/3左右,已经有网友进行过相关的测试。

    数据包

    对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
    而对于POST,某些厂商的浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

    因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。但是请注意以下实际情况:
    1、GET与POST都有自己的语义,不能随便混用。

    2、据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。

          而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。

    3、HTTP 协议中没有明确说明 POST 会产生两个 TCP 数据包。
          并不是所有浏览器都会在POST中发送两次包。
          而且实际测试(Chrome、Firefox)发现就只发送一次,header 和 body 不会分开发送。

          所以,header 和 body 分开发送是部分浏览器或框架的请求方法,不属于 post 必然行为。

    POST 方法比 GET 方法安全?【误解】

    GET请求参数是在URL后面的,数据在地址栏上可见;POST请求参数放在请求体重,数据在地址栏上不可见,因此有人说POST 比 GET 安全。
    然而,从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输的,只要在网络节点上捉包,就能完整地获取数据报文。
    要想安全传输,就只有加密,也就是 HTTPS。

    GET 会将数据缓存起来,而POST不会 ?【误解】
    经测试,使用ajax采用GET方式请求静态数据(比如html页面,图片)的时候,如果两次传输的数据相同,第二次以后消耗的时间将会在10ms以内(chrome测试),而POST每次消耗的时间都差不多。经测试,chrome和firefox下如果检测到GET请求的是静态资源,则会缓存,如果是数据,则不会缓存,但是IE什么都会缓存起来。

    是否缓存数据,不同的浏览器厂商的实现方式不一样。

    POST不能进行管道化传输 

    《HTTP权威指南》中是这样说的:http的一次会话需要先建立tcp连接(大部分是tcp,但是其他安全协议也是可以的),然后才能通信,如果 每次连接都只进行一次http会话,那这个连接过程占的比例太大了!于是出现了持久连接:在http/1.0+中是connection首部中添加keep-alive值,在http/1.1中是在connection首部中添加persistent值,当然两者不仅仅是命名上的差别,http/1.1中,持久连接是默认的,除非显示在connection中添加close,否则持久连接不会关闭,而http/1.0+中则恰好相反,除非显示在connection首部中添加keep-alive,否则在接收数据包后连接就断开了。
      出现了持久连接还不够,在http/1.1中,还有一种称为管道通信的方式进行速度优化:把需要发送到服务器上的所有请求放到输出队列中,在第一个请求发送出去后,不等到收到服务器的应答,第二个请求紧接着就发送出去,但是这样的方式有一个问题:不安全,如果一个管道中有10个连接,在发送出9个后,突然服务器告诉你,连接关闭了,此时客户端即使收到了前9个请求的答复,也会将这9个请求的内容清空,也就是说,白忙活了……此时,客户端的这9个请求需要重新发送。这对于幂等请求还好(比如get,多发送几次都没关系,每次都是相同的结果),如果是post这样的非幂等请求(比如支付的时候,多发送几次就惨了),肯定是行不通的。
      所以,post请求不能通过管道的方式进行通信!很有可能,post请求需要重新建立连接,这个过程不跟完全没优化的时候一样了么?所以,在可以使用get请求通信的时候,不要使用post请求,这样用户体验会更好,当然,如果有安全性要求的话,post会更好。管道化传输在浏览器端的实现还需考证,貌似默认情况下大部分浏览器(除了opera)是不进行管道化传输的,除非手动开启!

  • 相关阅读:
    linux之间文件共享的方式
    linux访问windows文件的方法
    linux下samba配置
    linux下ftp搭建
    windws下搭建ftp步骤
    索引的二元高度
    Oracle表的分析统计
    oracle———索引
    这些git技能够你用一年了
    使用 Composer 为 ThinkPHP(3.2.3)框架添加和管理组件
  • 原文地址:https://www.cnblogs.com/SavionZhang/p/11396403.html
Copyright © 2020-2023  润新知