TCP的三次握手四次挥手
2015-09-23 11:41
204 查看
一。三次握手
1.wireshark 抓包
2.TCP报文手部
注意标志位:
1).同步 SYN = 1 表示这是一个连接请求或连接接受报文。
2).只有当 ACK = 1 时确认号字段才有效。当 ACK = 0 时,确认号无效。
3).FIN = 1 表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。
3.连接示意
二。四次挥手
1.知所以然
为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)
放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部
发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意
现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
更明了的回答:由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一
个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行
关闭的一方将执行主动关闭,而另一方执行被动关闭。
2.图示
3. 2MSL(Maximum Segment Lifetime)存在的理由
TCP的TIME_WAIT状态也称为2MSL等待状态(1)让4次握手关闭流程更加可靠
4次握手的最后一个ACK是是由主动关闭方发送出去的,若这个ACK丢失,被动关闭方会再次发一个FIN过来。若主动关闭方能够保持一个
2MSL,则有更大的机会让丢失的ACK被再次发送出去。
(2)防止lost duplicate对后续新建正常链接的传输造成破坏。
lost duplicate在实际的网络中非常常见,经常是由于路由器产生故障,路径无法收敛,导致一个packet在路由器A,B,C之间做循环的
跳转。IP头部有个TTL,限制了一个包在网络中的最大跳数,因此这个包有两种命运,要么最后TTL变为0,在网络中消失;要么TTL在变为0之
前路由器路径收敛,它凭借剩余的TTL跳数终于到达目的地。但非常可惜的是TCP通过超时重传机制在早些时候发送了一个跟它一模一样的包,
并先于它达到了目的地,因此它的命运也就注定被TCP协议栈抛弃。
另外一个概念叫做incarnation connection,指跟上次的socket pair一摸一样的新连接,叫做incarnation of previous connection。
lost duplicate加上incarnation connection,则会对我们的传输造成致命的错误。大家都知道TCP是流式的,所有包到达的顺序是不一致的,
依靠序列号由TCP协议栈做顺序的拼接;假设一个incarnation connection这时收到的seq=1000, 来了一个lost duplicate为seq=1000,
len=1000, 则tcp认为这个lost duplicate合法,并存放入了receive buffer,导致传输出现错误。通过一个2MSL状态,确保所有的
lost duplicate都会消失掉,避免对新连接造成错误。
4.2MSL状态为什么设计在主动关闭这一方
(1)发最后ack的是主动关闭一方
(2)只要有一方保持TIME_WAIT状态,就能起到避免incarnation connection在2MSL内的重新建立,不需要两方都有
三。TCP连接出现大量TIME_WAIT的解决办法
一个TCP/IP连接断开以后,会通过TIME_WAIT的状态保留一段时间,时间过了才会释放这个端口,当端口接受的频繁请求数量过多的时候,就会产生大量的TIME_WAIT状态的连接,这些连接占着端口,会消耗大量的资源。面对这种情况可以通过修改TCP/IP的内核参数,来及时
的处理这些状态。
netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
执行该命令如果出现了大量的 TIME_WAIT 连接数目的话,如下:
FIN_WAIT2 30
CLOSING 33
TIME_WAIT 18000
vi /etc/sysctl.conf 然后,在这个文件中,加入下面的几行内容: net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_fin_timeout = 30 最后输入下面的命令,让内核参数生效: /sbin/sysctl -p
简单的说明下,上面的参数的含义:
net.ipv4.tcp_syncookies = 1
表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1
表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1
表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间。
此外,如果你的连接数本身就很多,我们可以再优化一下TCP/IP的可使用端口范围,进一步提升服务器的并发能力。
依然是往上面的参数文件中,加入下面这些配置:
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.ip_local_port_range = 10000 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000
这几个参数,建议只在流量非常大的服务器上开启,会有显著的效果。这几个参数的含义如下:
net.ipv4.tcp_keepalive_time = 1200
表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.ip_local_port_range = 10000 65000
表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为10000到65000。
将最低值设的太低,否则可能会占用掉正常的端口
net.ipv4.tcp_max_syn_backlog = 8192
表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets = 5000
表示系统同时保持TIME_WAIT的最大数量,如果超过这个数字,TIME_WAIT将立刻被清除并打印警告信息。
默认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接
字数量。
相关文章推荐
- Python网络爬虫 - 一个简单的爬虫例子
- hihocoder1236(北京网络赛J):scores 分块+bitset
- HTTP 错误 404.3 - Not Found(WCF+ASP.NET)
- XE8-indy10中TIdTCPConnection.Connected函数的源码
- 9.23 多线程学习 网络编程
- iOS学习---http协议
- TCP/IP 协议(三)
- HTTP请求的基本过程
- JavaScript学习总结(七)Ajax和Http状态字
- 【深度学习】卷积神经网络(Convolutional Neural Networks)
- 2015年下半年信管中高级网络面授直播课程(30课时)
- [iOS 多线程 & 网络 - 4.0] - AFN框架简单使用
- HttpPost,HttpGet,HttpPut,HttpDelete请求方式
- Httpclient对cookie的自动处理设置
- AFN框架使用
- http post请求
- HTTPS的七个误解
- OSI7层网络协议
- MD5登陆
- java http缓存