TCP(一)四次握手关闭一个TCP连接?
2017-12-31 本文已影响0人
杭州痞老板
一直以来的一个观点就是TCP通过4次握手即可关闭一个连接。但今天经过多次抓包测试,我发现真实的情形往往比教科书所写的4次握手机制更复杂。
测试的结论为有三种不同的关闭机制,分别为:4次握手关闭,3次握手关闭和异常关闭(通过发送RST包关闭TCP连接)
本着 实践出真理!要有图有真相!的方法论我做了如下测试以及相应的记录!
本次的实验工具为chrome浏览器,实验方法是在地址栏上输入一个图片的URL并回车,并通过wireshark来抓包。
在我的测试样本中,划分为3种不同的情形,如下所述
1. 图片请求完后不关闭浏览器
这种情况确实是最常见的
当服务器在发送完一个http响应包之后,若等待一分钟内(测试大约为60秒)监测到这个插口对上没有新的http请求包,则会主动来关闭连接(发送FIN包),客户端在收到FIN包后会做出响应(发送ACK包),这个步骤是没有问题的,问题是对于之后的步骤测试中出现了3种情况!
1.1 客户端自动发送FIN包,服务器收到后返回ACK包确认
这个是教科书版本的四次握手关闭
1.2 客户端自动发送FIN包,但是服务器直接舍弃并发送RST包
在发送完ACK包之后,客户端会自动去发送FIN包,但是服务器直接舍弃了这个FIN包,并发送一个RST包来异常关闭这个连接!
1.3 客户端发送2次检测包后,服务器发送RST包
实验测试表示:客户端会发送2次检测包以维持TCP连接,服务端在发完FIN包之后累计收到2次检测包后便会发送RST包来中断连接。
【概括来说,第一种是正常关闭,第二和第三中情形均为异常关闭(目前仍不清楚由哪些原因导致)】
2. 图片请求完后立即关闭浏览器
通过测试可以发现,当关闭浏览器后,所有通过该浏览器建立的TCP连接会发送FIN包来表示关闭连接
握手关闭的三个TCP包都罗列在红框内:
有两个发现:
- 在一分钟内的等待期内,若客户端主动来发送FIN包后,服务器一收到客户端发来的FIN包,便提前发送FIN包来响应(而不是等到等待期结束后再发送)
- 客户端主动关闭的情况下,两端仅通过了三次握手即关闭了连接(服务器将ACK包与自己要发送的FIN包组合在了一起一并发送了【标准关闭机制中的第二步和第三步合在了一起】)
3. 图片请求完后等收到服务器端发送的FIN包后,再关闭浏览器
在收到服务器端发送的FIN包并发送完ACK包之后,我把浏览器关闭了,此时也便得到了教科书版本的四次握手关闭!
最后还是有必要来总结一下的:
这次的测试过程不仅发现了TCP灵活多变的握手关闭机制
还是有些额外的收获
- 浏览器HTTP请求的过程,大多都是服务器主动去关闭连接(除非是http请求完的1分钟内关闭浏览器,但这是不常见的情形),所以服务器会有大量的TIME_WAIT状态的TCP连接,这种情况下必须要缩短TIME_WAIT的时间,不能使用默认的4分钟(2msl),否则当积累太多的TIME_WAIT状态的TCP连接后,服务很容易挂掉!
- 客户端对服务器同一个插口(例如:106.14.17.171:80)的间隔一分钟内的多次http请求,浏览器会复用为现有的TCP连接并基于此进行多次http请求,而不是客户端为每一次http请求单独占用一个新的插口。
- 第一次尝试用Markdown写日志,写作如行云流水,特别舒畅!为Markdown疯狂打call!