背景
以前被人问起GET请求与POST请求区别。一般人都能答出:
- 长度、安全、浏览器后退,历史记录等行为不同
- get一般用于查询数据,post一般用于写入数据
然后有人提出了一个杀手锏的区别,99%的人都不知道,那就是:GET产生一个TCP数据包;POST产生两个TCP数据包。
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
参考这篇文章的观点:
http://gold.xitu.io/entry/57597bd45bbb500053c88b4c
情况真的是这样么?我们来验证下!
实验
我们先跑一段基于node平台的webserver程序,开始监听http://127.0.0.1:9090
require('net').createServer(function(sock) {
sock.on('data', function(data) {
sock.write('HTTP/1.1 200 OK\r\n');
sock.write('Transfer-Encoding: chunked\r\n');
sock.write('\r\n');
sock.write('5\r\n');
sock.write('12345\r\n');
sock.write('0\r\n');
sock.write('\r\n');
});
}).listen(9090, '127.0.0.1');
打开wireshark,捕获Loopback接口(因为我们捕获的是服务端地址是127.0.0.1,不需要捕获其它网卡接口),过滤规则:tcp.port == 9090
测试GET请求
我们先用postman发起get请求并带一个test
参数即http://127.0.0.1:9090/?test
。
wireshark得到如下记录:
图get-1
当前选中帧,为postman向webserver发送数据的帧。点开进一步观察
图get-2
从图get-2发现这一帧确实发送了消息头和实体(当前选中行应该是表示消息头结束,下面就是body) 从图get-1也看到,第6帧是webserver端给postman的响应。证明get请求已发送完毕。
再测试POST请求
参数为hehe
图post-1
图post-2
似乎我们在这一帧直接就看到了请求body我们的参数hehe
.看来并不是发送了两个数据包。
但是这个观点总不是空穴来风吧。有可能是wireshark这款工具使用问题,或者看不出来。
我接着增大了参数的大小,也就是扩大了body(增加到了1000个字符左右)
图post-3
图post-4
从图post-4中看出这次的http请求由两帧组成,也就是post-3选中的第63帧和当前打开的64帧,查看63帧详情时,果然只有消息头
, 64帧是body内容。跟上面文章的观点基本一致。唯一不一致的是并没有看到server返回状态码100之类的信息,第65帧就server端对客户端63帧的响应。
那get请求也会因为参数增大而发两个包么?
我作了进一步实验,并没发现此现象。
图get-3
结论
get请求确实只发送了1个包
post请求在参数少时也只看见发送了1个包,在参数增大时,发现确实在消息头和body被分割成了两个包,甚至根据body大小,分割成更多包。
申明
实验环境基于mac,postman,wireshark,传递参数大小仅验证了字符hehe
和 “1000个字符” 长度数据。可能具有一定不准确性。