linux TCP流量控制

I.流量控制
TCP使用流量控制来管理数据流量。流量控制限制发送字节大小,防止接收方接收缓存溢出。
  1.发送方发送数据速度比接收方处理速度高;这种情况会使接收方缓存溢出,引起数据段被丢弃
  2.应用取socket中的缓存数据存在间隔,所以只会偶尔出现缓存为空的情况;比如多媒体数据的接收速度高于播放速度
所以流量控制可以避免因接收方缓存溢出而产生的数据包丢弃,引起不必要的重传

TCP使用滑动窗口机制来实现流量控制

 

II.滑动窗口机制
i.滑动窗口机制
滑动窗口机制主要用在传输层协议或面向连接协议中,主要完成以下任务:
  1.发送多个数据包时,在接收端按发送顺序进行重排(乱序包重排),以保证接收数据顺序与发送数据顺序相同
  2.根据数据包的序号,可识别数据包丢失与重复;由数据包的重传机制实现可靠数据传输。
  3.根据窗口大小控制TCP数据流量
通过TCP头中以下字段实现上述功能:
  1.Sequence Number,对数据进行连续编号,表示数据包第一字节数据编号;
  2.Acknowledgment Number,表示已经正确接收的数据编号+1
  3.Window,窗口大小,表示还能接收多少数据

下图可以看出滑动窗口怎样实现流量控制:

上图表示快速发送端A向慢速接收端发送数据,窗口大小为4096
1-3:表示握手阶段,协商窗口大小、MSS等信息
4-7:发送4096字节数据,超出发送窗口,等待确认和新窗口
8:确认已经接收的数据
9:通知新窗口
10-15:重复上述情况
16-17:表示挥手阶段

滑动窗口主要信息如下图所示:
发送方

接收方

snd_una:在接收到ack报文后,移动snd_una
snd_wnd:在接收到syn报文或ack报文后,根据window值更新snd_wnd
rcv_wup:发送window值时,更新rcv_wup
rcv_wnd:根据窗口阈值等信息在发送window时,更新rcv_wnd
注意:如果rcv_nxt+新接收数据段长度>rcv_wup+rcv_wnd,会出现数据溢出,进而引起数据包丢弃;直到rcv_wup+rcv_wnd>=rcv_nxt+新接收数据段长度,才能接受新数据


ii.窗口滑动
1.发送窗口滑动
tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_established->tcp_ack->tcp_ack_update_window
更新snd_una,将发送窗口向前移动

2.接收窗口滑动
tcp_sendmsg-> __tcp_push_pending_frames->tcp_write_xmit->tcp_transmit_skb->tcp_select_window
更新rcv_wup,将接收窗口向前移动

iii.发送窗口超出检查:
tcp_sendmsg-> __tcp_push_pending_frames->tcp_write_xmit->tcp_snd_wnd_test
如果当前数据包最后一字节序号>snd_una+snd_wnd,则暂不发送该数据包,以控制发送数据流量

iv.接收窗口超出检查:
快速模式时:
  Predicted packet is in window by definition. * seq == rcv_nxt and rcv_wup <= rcv_nxt.所以不用做接收窗口检查
慢速模式时:
  tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_established->tcp_validate_incoming->tcp_sequence,做接收窗口检查

v.零窗探测
当接收方没有缓存时,会通过ack报文中window=0通知发送方,发送方不能再发送数据。
窗口大小在ack报文中发送,当接收方不向发送方发送数据或接收方的发送窗口为0时,由于发送方的发送窗口为0也不能再发送数据,这样双方就会永远的等待下去。
零窗探测机制主要解决上述问题;通过设置一个零窗探测时钟,当时钟超时时,会发送一个仅有TCP报文头的包到接收方;如果接收方有缓存,就会在ack报文中通知接收方的接收窗口大小。
1.零窗探测时钟处理函数初始化
socket手动创建:
inet_create->tcp_v4_init_sock->tcp_init_xmit_timers->tcp_write_timer->tcp_probe_timer
socket自动创建(listen端):
tcp_v4_rcv->tcp_v4_do_rcv->tcp_v4_hnd_req->tcp_check_req->tcp_v4_syn_recv_sock->tcp_create_openreq_child->tcp_init_xmit_timers->tcp_write_timer->tcp_probe_timer
2.零窗探测时钟启动
tcp_v4_connect->tcp_connect->inet_csk_reset_xmit_timer->sk_reset_timer
3.零窗探测时钟处理函数
tcp_probe_timer->tcp_send_probe0

III.窗口大小
i.窗口大小标度
Window占16位,最大表示值为2^16-1=65535,现在已经完成不了要求,例如一个连接的传输速率为10Mbps,往返时间为100ms,要恒量数据流传输,至少需要10Mbps*100ms=125000 Bytes窗口大小;所以添加了TCP Window-Scaling选项,用来增大窗口上限。
Window-Scaling Option格式为:
Type:3(1Byte)+Len:3(1Byte)+Shift Count(1Byte)
Shift Count最大值限制为14,所以表示的最大窗口值为2^16*2^14=2^30
Window-Scaling Option只能在SYN或SYN-ACK报文中发送,即握手阶段
telnet TCP连接抓包如下,Shift Count一个是6,一个是2:

tcpdump -vvv tcp port 23
18:26:08.187741 IP (tos 0x10, ttl 64, id 5778, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.1.29.58542 > 10.20.146.15.telnet: Flags [S], cksum 0xe9b4 (correct), seq 2575510789, win 5840, options [mss 1460,sackOK,TS val 44972951 ecr
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值