tcp option-sack

一直以来,对sack都只是有所耳闻,最近产品的一个bug让我比较深入的了解了下。

什么是sack

更准确的说法是s ack,而不是sack,因为全称是selective acknowledgment,翻译过来是选择性确认。tcp头部中的ack确认序列号大家应该都比较了解了,正常情况下确认序列号等于收到的对端报文的序列号+payload length,假如本端发送的确认序列号为x,则说明对端发送的到x为止的数据我都收到了,对端下一个数据包的序列号应也为x。
sack包含两个tcp选项,都放在tcp option中。一个是SACK-Permitted选项,这个选项只会在tcp连接建立的时候使用,也就是双方在三次握手中的前两个包中协商本次连接中是否支持sack;另一个是sack选项,该选项参数告诉对方已经接收到并缓存的不连续的数据块,发送方可根据此信息检查究竟是哪些块丢失,从而发送相应的数据块。受 TCP 包长度限制,tcp option最多只有40字节,一个sack字段的长度一般为10字节,所以TCP包头最多包含四组SACK字段。

基于sack的快速重传

  1. 超时重传
    假如三次握手中出现丢包(还没来得及使用sack),tcp协议会遵循超时重传的原则。tcp协议栈通过某种算法计算出rto,当rto时间内没有收到ack包,则认为丢包,开始超时重传,值得一提的是,超时重传的的时间是按指数递增的,比如第一次是1s,第二次是2s,第三次是4s。
  2. 快速重传
    当TCP 发送端在观测到至少dupthresh(一般为 3)个重复ACK序列号后,即重传可能丢失的数据分组,而不需等待重传计时器超时。sack会选择性确认丢包之后的报文,但是ack不会,所以即使出现丢包触发了sack,ack序列号也不会增加。
    开启sack的快速重传如下图所示,红色虚线的包丢失了,客户端收到了连续三个携带sack的ack包,且三个ack包的确认序列号都一样,所以立即重传了100序列号的包。
    在这里插入图片描述

遇到的问题

最近遇到的一个问题也与sack有关,大概是测试的产品在第三次握手时会对入向数据包tcp头部插入一个字段,所以需要将后续所有入向报文的序列号加上这个字段的长度,然后将出向的确认序列号减去这个字段的长度,这些都没有问题,问题出在入向丢包的时候,会触发服务器的sack,而产品没有对sack的序列号做偏移,导致客户端认为对端确认了还没有发出去的数据,连接出现异常。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值