最近连续看了一个微信公众号小林coding的图解网络的文章,收获挺多。在这里发文小结一下,也方便后续工作中查询。
如何在不kill进程的情况下关闭TCP连接
Linux有一个工具killcx, 可以关闭TCP连接。原理就是伪装客户端发送一个SYN报文,一般情况下这个报文的序列号不会是当前滑动窗口中的有效序列号,服务端会回一个ACK报文(称之为Challenge ACK),带上期待的序列号。收到了ACK报文后,再分别以ACK的序列号和期待的应答序列号发送RST报文给客户端和服务端。客户端和服务端收到了RST报文,都以为是对端发送的,就会关掉连接了。
这个就是黑客干的活,无故切断连接。
序列号为什么每次不一样
主要是为了避免接收到历史报文后,降低历史报文序列号在有效窗口内的概率。如果不再有效窗口内,报文会被丢弃,而不会对正常流程产生影响。
为什么要有TIME_WAIT状态
TIME_WAIT状态是主动断开连接方在发送完FIN_ACK后,延迟关闭连接。这个时间足以使两个方向的包在网络中自然消失,而不会留到下一个连接中。同时保证对端可以正常关闭,防止会给对端的FIN_ACK丢失,继续处理对端重传来的FIN报文。
什么情况下SYN报文被丢弃
在开启了tcp_tw_recycle参数,并且在NAT环境下,造成SYN报文被丢弃。主要是NAT环境下有个PAWS机制,根据IP作防止回绕的,经过NAT后的多个客户端被当成同一个了,无法区分了。
另一种情况就是accept队列慢了,新的syn报文就被丢了。
TCP如何保证按序可靠交付报文
TCP是一个可靠的传输协议,如何保证可靠呢?传输过程中的数据包破坏、丢包、重复以及分片乱序如何处理的?
TCP通过序列号、确认应答、重传机制、连接管理和窗口控制等机制来保证。
重传机制
主要有四种重传: 超时重传、快速重传、SACK、D-SACK
超时重传就是发送方在指定时间没有收到接收方应答的ACK。可能是发送包丢失或者ACK包丢失,阻塞了。这个是以时间来衡量是否需要重传的。
快速重传收到多个ACK的下一个报文序列号相同的,触发重传对应的报文或者是之后的报文,具体根据实现来决定。
SACK就是接收方在TCP首部会发送缓存的地图,发送方就可以知道要选择重传那些报文了。
D-SACK 使用SACK告诉发送方哪些数据已经被接收了。发送方就知道哪些包丢了,发送那些包就行了。
滑动窗口
就是约定一个窗口的大小,在这个范围内不需要等待ACK可以直接发送。提高发送的效率。窗口大小是接收方决定的,就看接收方可以缓存多大的数据包。
流量控制
当应用程序来不及取走数据时,可用窗口会渐渐的变成0. 窗口开放后,接收方会发送一个端口开放的ACK。 如果ACK丢了,发送方会超时探测窗口大小,获取到新的窗口后再决定发送数据。
糊涂窗口综合症
就是窗口太小了,然后发送方每次只放松很少的数据,占用带宽。可以使用Nagle算法来解决。 只有窗口>=MSS 或者数据 >=MSS, 并收到了之前的ACK才发送数据。
也可以不让接收方回小窗口的报文。当接收窗口 < MSS/2时,直接调整窗口大小为0。
拥塞控制
根据网络拥塞情况,发送方调整发送的数据量,防止过多的报文重传造成网络更加拥塞。 发送方没有再约定时间接收到ACK包,就认为网络拥塞了,然后减小拥塞窗口,相反的 就会加大拥塞窗口。
慢启动 拥塞避免 拥塞发生 快速恢复
后面的具体内容比较详细,不一一记录了。
更多
TCP是一个复杂的协议,在协议的算法及约定上面也采取了很多巧妙的设定。为了优化协议或者是解决问题,进行了多种考量。同时也提供了许多参数设定。精彩之处,需要多次学习,一点点吃透,有待挖掘更多的知识,先这样了。
行动,才不会被动!
欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。