本文是 Docker 下 Java 文件上传服务三部曲的终篇, 前面两章我们创建了客户端和服务端, 实战了文件上传服务, 本篇我们通过 wireshark 工具抓包, 分析上传文件时的网络请求;
前文简述
Docker 下 Java 文件上传服务三部曲旨在实战 Docker 下的 java 文件服务的开发和部署, 前面两章的地址如下:
1. Docker 下 Java 文件上传服务三部曲之一: 准备环境;
2. Docker 下 Java 文件上传服务三部曲之二: 服务端开发;
此外还有一篇文章通过阅读源码来学习 SpringMVC 的文件服务: SpringMVC 源码分析: POST 请求中的文件处理;
为何要用 wireshar 抓包分析?
前面两章已完成了 Java 文件上传服务的实战, 本章不会有新的开发了, 为什么还要专门写一篇有关抓包分析的文章呢?
因为我对一个概念很模糊: 所谓的一次 POST 请求, 一次怎么理解?
读者您可能觉得我的问题没描述清楚, 其实我也没办法说得更准确了, 因为本来就不清楚
所以还是借助 wireshark 让 POST 背后的细节现形吧
实战环境
如下图, 像三部曲的第一章那样用两台电脑进行实战, 一台 win10 作客户端, 一台 ubuntu 作 server,win10 发起 POST 请求将文件上传到 ubuntu 上:
ubuntu 电脑上的 Docker 容器是通过以下命令部署的:
docker run --name fileserver001 -p 8080:8080 -idt bolingcavalry/springbootfileserver:0.0.1-SNAPSHOT
wireshark 安装在 win10 电脑上, 抓包分析;
抓包, 从简单的开始
我们来试试抓包, 一开始先抓个简单的 GET 请求的, 刚才部署的 Docker 容器提供了一个 GET 接口, 假如 ubuntu 电脑 IP 地址是 118.24.0.64, 在浏览器可以通过这个 URL 访问: http://118.24.0.64:8080/hello
响应是个字符串, 如下图所示:
接下来我们就来抓这个请求响应的包:
1. 打开 wireshark 应用, 选好对应的网卡(例如我是在局域网中, 所以选的是 WLAN);
2. 设置过滤规则, 假如 ubuntu 电脑 IP 地址是 118.24.0.64, 那么过滤规则就是 ip.src == 118.24.0.64 or ip.dst == 118.24.0.64, 意思是只展示发往 118.24.0.64 的数据和 118.24.0.64 返回的数据, 设置方式如下图所示, 请按照数字的顺序进行操作:
3. 为了抓到纯净的数据, 请不要再和 ubuntu 电脑有其他连接, 例如 SecureCRT 等工具如果还有连接请立即关闭, 否则按照上述过滤规则也会将 ssh 协议的数据抓到;
4. 打开 chrome 浏览器的隐身窗口, 地址栏输入: http://118.24.0.64:8080/hello
5. wireshark 抓到的数据如下图所示:
如上图所示, 我们看到了 TCP 握手, 握手成功后客户端发起 GET 请求, 服务端收到后立即 ACK, 然后再以 HTTP 协议向客户端返回数据;
然后, 我们还看到了保持连接的 Keep-Alive 包, 以及关闭连接的 FIN 包;
然后, 浏览器还在尝试着通过 Keep-Alive 保持连接;
GET 请求的抓包就到这里吧, 接下来看看 POST 请求的抓包;
POST 请求抓包
像前两章那样在 win10 电脑上运行 UploadFileClient 类, 将 win10 上的文件 POST 到 ubuntu 电脑上, 抓到了如下图的包:
这么多数据包, 看来所谓的一次 POST 请求, 果然没那么简单.
本次 POST 的文件大小为 150K 左右, 上图红框中, POST 请求的大小才 307 字节, 所以本次上传的文件数据, 并不是 HTTP 协议上传到服务端的, 而是通过下图红框中那些备注为 TCP segment of a ressembled PDU 的 TCP 包上传上去的:
TCP segment of a ressembled PDU 是指 TCP 层收到上层大块报文后分解成段后发出去, 所以 150K 的文件被拆分成了多个 TCP 包发送;
此处有个小疑问, 如下图, 为什么每个 TCP 包的数据段大小都是 1424 呢?
我们看看最开始 TCP 握手时的协议, 如下图:
如上图红框所示, TCP 握手的时候, 服务端的 [SYN, ACK] 包中规定了 MSS=1424, 所以后面的 TCP 包中数据段都没有超过此大小;
现在终于清楚了, 一次 POST 请求, 并不等于一个 http 协议的数据包, 实际上在 TCP 层会有多个包负责整个数据的传输, 并且这些包都会有来自服务端的 ACK;
至此, Docker 下 Java 文件上传服务三部曲就全部结束了, 希望此系列能够帮您加深对文件服务的理解, 更希望能在实战中帮助到您;
来源: http://blog.csdn.net/boling_cavalry/article/details/79380053