Wireshark 网络包分析实战二:SACK

Overview

本文的主角是TCP SACK机制,首先讲清楚为什么我们需要SACK机制,其次通过wireshark抓包展示真实世界中的SACK,再者引申经常与SACK一起出现的概念,讲清楚SACK机制并不是孤立的概念。要真正解决现实中的问题,是需要与其他TCP协议内容一起作用滴!

为什么需要SACK

在讨论为什么需要SACK之前,我们应该先了解TCP接收数据的一个机制:它只能确认连续的数据,它也只能消费前面的连续数据。

TCP is never able to acknowledge data it has received correctly but that is not contiguous A receiving TCP prevents applications from consuming data beyond a hole because of the byte stream abstraction it provides.

举个例子:

比如sender发送了10个包:#1,#2,#3,#4,#5,#6,#7,#8,#9,#10,但是#5在中途丢失了,对于senderreceiver来说,就好比数据中间产生了一个"洞"hole

tcp接收方receiverack只能是接收了#4,表示该接收#5了。再一次重申,因为tcp协议的ack机制只能接收连续的数据,如果#5丢失了,即便#6#7#8#9#10全部到达receiverreceiver也无法跨过#5告诉sender我只是丢了#5,后面的包到没到达sender是不知道的。

此时sender该怎么做?sender不知道具体情况,它只能一股脑将#5,#6,#7,#8,#9,#10全都重新发送一次。

像上面的情形:在一连串数据的发送过程中,中间的数据包很有可能丢失,如果每次都是重新发送一遍,首先效率低,其次浪费网络链路带宽。

如果sender能够得知自己发送的数据中间产生了一个洞(中间数据包丢了),那就太好了,因为如此一来,sender就可以对症下药的发送真正缺失的数据。

sender怎么才能知道这一信息呢?只能靠receiver的配合,receiver根据自己的接收情况告诉sender发送过程中产生的"洞"

If a TCP sender were able to learn of the existence of holes at the receiver, it could better select which particular TCP segments to retransmit when segments are lost or otherwise missing at the receiver.

没错,所谓SACK就是Selective Acknowledgementselective指的就是上述select lost segments to retransmit,怎一个妙字了得。

关于SACK的概念,我们就介绍到这里,下面根据真实案例来学习SACK的细节。

真实世界中的SACK

经过抓包,你会发现SACK经常会和两个好兄弟一起出现。

它们分别是Wireshark Expert Infos中的「TCP previous segment not captured」和「TCP Dup ACK」。

下面直接来看数据包的抓取吧~

发送者sender的端口为30000,接收者receiver的端口为1479

再给出具体分析之前,大家可以先自己看看,注意表头的含义。

那么,现在我们开始分析。

#10415号包

receiver说:嘿,前面的数据我都接收到了,接下来麻烦你从seq=9163441开始发送的

psTCP Len的长度为0,表示这个包只是一个ack包,没有携带任何应用数据。

#10416号包

sender说:好的,俺这就从seq=9163441开始发送,并且我带了1320 bytes的数据,我下一个数据包从seq=9164761起开始发送哈~

ps:到这里一切都没有问题。

#10417号包

开始发生意外了,何以见得?wireshark提示「TCP previous segment not captured」了。

为什么呢?因为数据不连续了。

10416号包说下一个从seq=9164761开始发送,结果10417号包的seq=9175321,中间还有一堆数据没有发送呢!

wireshark意识到中间可能有点问题,就即使提醒我们了。

这不就是一开始举例子的时候说的那样,连续发送包,然而中间丢失了数据,但SACK能够记录这一事件。接下来就看10418到底是如何处理的!

#10418号包

receiver:我宣布两件事,1)我的Ack=9164761,表示#10416号包的数据我接收到了。2)我的TCP Option中有SACK信息,9175321-9176641表示#10417号的内容我收到了。sender你知道了吗?

#10419号包

sender:接着#10417的内容,俺继续发送(我还没意识到我需要重传前面的一些数据)

#10420号包

receiver:咳咳,我再次重申,我的Ack=9164761,表示#10416号包的数据我接收到了,这已经不是我第一次Ack这个seqTCP Dup ACK),请sender注意📢。其次,你发的其余数据包我都接收到了,请看我的TCP OptionSACK的部分。

你有没有恍然大悟,为了让事情变得更清晰,让我们再次从全局看一下这次的抓包情况:

首先来看红色和蓝色箭头部分:receiver一直声明自己的ack=9164761,表示自己按照顺序接收到了此ack之前的所有数据,但是它一再声明(TCP Dup Ack)我只连续收到这里,后面的数据包可能确实一段数据或者多段数据,具体请看我的SACK中的信息。

然后就是receiver中的SACK信息,绿色方框部分表示receiver跨过可能丢失的数据段,左侧范围一直从seq=9175321开始,而这正好是#10417包发送的数据内容。后面随着sender不断发送数据,receiverSACK右侧范围不断扩大,这一点从黄色方框谁可以看出来的。

引申问题

所有的sender和receiver都可以使用SACK机制吗?

不是的,是否可以使用sack机制,在三次握手的过程中确定。

只要双方在TCP Option中,都明确的开启SACK permitted才表示接下来的数据传输过程中,可以使用SACK机制加快数据传输的恢复。

为什么要有TCP Dup Ack,它是干啥的?

一句话回答:receiver通过SACK告知sender可能缺失的数据,Dup Ack告诉sender重新发送的实机。

Dup Ack顾名思义,就是receiver重复声明,俺已经接收过某某包了。你仔细一想,其实这是SACK出现必不可少的辅助。

对于网络链路来说,除了丢包,还有可能出现乱序的情况。

比如发送#1,2,3,4,5,本来是顺序发送的,结果经过不对称的网络链路,发生了乱序,receive收到的顺序为13245

receiver接收到#1,然后发送ack=#1

receiver接收到#3,表示发送ack=#1sack=#3

sender接收到以后要立马发送#2吗?不需要的,因为receiver紧接着就会收到#2,从此中间数据缺失产生的洞就补上了。因为这种场景仅仅是乱序,是不需要重传的?

那如何才能区分乱序和丢包呢?其实这是很难的,TCP协议能做的,就是尽量区分一下,也就是所谓的妥协。

TCP如何认为这是需要重传的呢?

一定时间内,接连收到三次及以上同样ackDup Ackwireshark就认为这包啊,sender需要重传了,否则sender不必过多关注这一信息。

Summary

关于SACK,我表达清楚了吗?

相关推荐
咩咩大主教3 小时前
C++基于select和epoll的TCP服务器
linux·服务器·c语言·开发语言·c++·tcp/ip·io多路复用
城南云小白4 小时前
web基础+http协议+httpd详细配置
前端·网络协议·http
Tony聊跨境5 小时前
什么是 SSL 代理?
网络·网络协议·ssl
汀、人工智能6 小时前
报错error: RPC failed,curl 16 Error in the HTTP2 framing layer解决方法
网络·git·网络协议·rpc
就这个java爽!8 小时前
JAVA网络编程【基于TCP和UDP协议】超详细!!!
java·开发语言·网络·tcp/ip·udp·eclipse·idea
一叶飘零_sweeeet9 小时前
为什么 Feign 要用 HTTP 而不是 RPC?
java·网络协议·http·spring cloud·rpc·feign
KookeeyLena79 小时前
动态IP与静态IP:哪种更适合用户使用?
网络·网络协议·tcp/ip
时之彼岸Φ10 小时前
Web:HTTP包的相关操作
网络·网络协议·http
秋已杰爱10 小时前
HTTP中的Cookie与Session
服务器·网络协议·http
W215510 小时前
LINUX网络编程:http
网络·网络协议·http