从TCP层面分析POST请求

来源:转载

1.问题的提出

前段时间参加一个公司的面试,面试官提出一个问题:请从底层的角度分析HTTP协议中的POST和GET的区别。


当时我没能回答这个问题,后面问面试官这个问题,结果他也没有答出来。自己回来的路上一路思考并且搜索了相关的资料,网上的说法是:POST是分成两个TCP发出去,一个是Header头部分的TCP包,一个是Body的TCP包。自己心里面怀疑这个答案是否正确,因为如果按照网上的说法来进行系统设计的话,存在一定的性能问题,因为只包含header的TCP包的话肯定比较小,这个TCP包本来可以装更多的内容的,所以对网络的性能存在一定的浪费。


基于上述的怀疑,自己决定使用wireshark对POST方式的HTTP请求进行抓包,因此有了这一篇文章。


2.客户端和服务器端的代码
2.1 客户端的POST请求代码

写了一个简单的form页面,代码如下:






Title








2.2 采用Postman作为客户端

分别将postman作为独立软件和chrome插件两者方式进行测试。


2.3 服务器端的代码

服务器端的代码很简单,直接把post提交的内容显示出来即可,代码如下:


<?php
var_dump($_POST);
3.测试结果
3.1 使用Chrome的原生form页面提交
3.1.1 大批量内容发送

我们使用大量的文字进行发送,使用的浏览器是chrome 63:


我们可以看到,这次TCP请求是分成4个tcp segment进行发送。我们再查看一下第一个TCP包:



从tcp的内容可以看到,该数据表只包含HTTP的Header部分,不包含Body的内容。


3.1.2 少量内容发送

我们接下来使用少量的文字进行发送,Chrome可以一次性的发送所有内容到服务器:



我们可以到Chrome没有进行TCP分包发送,一个TCP包就发送了所有的内容。


3.2 使用Firefox的原生form页面提交
3.2.1 大批量内容发送

我们使用大量的文字进行发送,使用的浏览器是Firefox 57:



我们可以看到,在发送同样的大批量内容的情况下,Firefox是分成了3个tcp segment发送,我们查看一下第一个TCP包:



我们看到,Firefox的第一个TCP已经不仅包含了HTTP中的Header的内容,而且包含了部分Body的内容。


3.2.2 少量内容发送

我们接下来使用少量的文字进行发送:



Firefox的结果和Chrome一样,都是一个TCP包把内容发完。


3.3 使用Postman(浏览器插件模式)进行POST提交
3.3.1 大批量内容发送

因为Postman是以浏览器插件的形式运行的,所以结果基本和上面Chrome的结果一样:



Postman发送的第一个TCP包:



和Chrome的结果一样,第一个TCP包只有HTTP中Header的内容。


3.3.2 少量内容发送

与Chrome的结果一样,一个TCP包把全部内容发完:



3.4 使用Postman(独立软件模式)进行POST提交

由于在Postman的官网上,出现了新版的Postman,它作为一个独立的软件出现,不再是一个Chrome的插件,我们同样对其进行了测试:


3.4.1 大批量内容发送


我们可以看到它和作为Chrome插件的Postman在TCP包的分割上有不同,发送同样的内容,这里是分割成为3个TCP Segments的,而插件版的Postman是分割成4个TCP Segments的。


我们在看看第一个TCP包的情况:



第一个TCP包已经包含有HTTP协议中Body的部分内容。


3.4.2 少量内容发送

和其他测试的结果一样,一个TCP包把全部内容发完:



3.5 使用PHPStorm自带的rest测试工具进行POST提交(底层是Apache HttpClient 4.5.2)

具体的设置如下:



3.5.1 大批量内容发送


我们可以看到是分成了3个TCP Segments进行发送的,我们再看一下第一个TCP包的内容:



可以看到,第一个TCP不仅有HTTP的Header的内容,还带有部分Body的内容。


3.5.2 少量内容发送


和其他的客户端一样,都是一个TCP包发完。


4.总结

上面进行了5个客户端的抓包测试,我们把结果总结成以下的表格:



客户端大批量内容发送分成的TCP Segments数量第一个TCP的内容少量内容发送的TCP Segments数量

Chrome634Header1
Firefox573Header+Body1
Postman(浏览器插件模式)4Header1
Postman(独立软件模式)3Header+Body1
PHPStorm(底层是Apache HttpClient)3Header+Body1

通过上述的测试,我们发现文章开头提到的“POST是分成两个TCP发出去,一个是Header头部分的TCP包,一个是Body的TCP包”是错误的,在一个TCP包能所有内容发完的情况下,只发一个TCP包,不会把HTTP的Header和Body的内容分成两个TCP包。

分享给朋友:
您可能感兴趣的文章:
随机阅读: