tcp协议之报文发送流程

tcp协议之报文发送流程

tcp_sendmsg函数

在这里插入图片描述
以tcp_ipv4协议栈为例通用发送函数为tcp_sendmsg->tcp_sendmsg_locked

在这里插入图片描述
在tcp_sendmsg_locked函数中主要发送会通过__tcp_push_pending_frames和tcp_push_one和tcp_push进行报文发送的判断。forced_push(tp):检查是否需要强制推送(如紧急数据标记urg标志存在)
tcp_mark_push():将skb的标志设置为需要推送(PSH位)__tcp_push_pending_frames(): 从发送队列推送已经准备好的报文。否则如果skb是队列头,只推送队列头一个报文。

其中while循环的主要工作为将需要发送的消息内容复制到skb_buff结构体中并添加到sk->sk_write_queue队列中即发送缓冲区中。

tcp_write_xmit函数

在这里插入图片描述

struct sock *sk: 表示sockets对象,用于操作TCP连接相关信息
unsigned int mss_now: 当前MSS值,用于计算分段长度
int nonagle: 是否使用Nagle机制,控制是否合并小包发送
int push_one: 控制是否只发送一个包分段
push_one > 0 时,只发送一个包分段
push_one == 2 时,忽略拥塞窗口限制,强制发送一个包分段
gfp_t gfp: 内存分配标志位,用于申请TCP发送需要的内存

在tcp_write_xmit函数中while ((skb = tcp_send_head(sk)))循环读出sk缓存区中待发送报文
其中循环中存在多个判断,例如采用Nagle机制,控制合并小包发送则会在break;将会导致此次tcp_write_xmit函数并不会实际发送报文。其中tcp_pacing_check表示如果已经开启了tcp pacing功能和pacing_timer报文调度定时器已经设置则在此次tcp_write_xmit函数中不会进行实际的报文发送。
在这里插入图片描述
在这里插入图片描述

所有判断完成后最终会调用tcp_transmit_skb并调用 icsk->icsk_af_ops->queue_xmit(sk, skb, &inet->cork.fl);将报文发送给ip层。

tcp定时函数

在这里插入图片描述
使用inet_csk_init_xmit_timers初始化TCP连接需要的3个定时器:重传定时器;延迟ACK定时器;心跳定时器。

在这里插入图片描述
在这里插入图片描述

通过inet_csk_reset_xmit_timer函数设置重传定时器的定时时间并在回调函数tcp_write_timer->tcp_write_timer_handler中根据event的状态进行报文的重新发送的选择。

ICSK_TIME_RETRANS: 重传定时器,用来触发数据包重传。
ICSK_TIME_DACK: 延迟ACK定时器,用来控制ACK发送频率。
ICSK_TIME_PROBE0: 零窗口探测定时器,当接收窗口为0时用来探测是否窗口开启。
ICSK_TIME_EARLY_RETRANS: 早期重传定时器,触发早期重传方式优化网络延迟。
ICSK_TIME_LOSS_PROBE: 尾丢包探测定时器,用来处理尾丢包情况。
ICSK_TIME_REO_TIMEOUT: 重新排序定时器,用来检查报文顺序是否混乱。

如果icsk->icsk_timeout大于当前时间jiffies则重新设置icsk_retransmit_timer定时器。

tcp pacing

在tcp_init_xmit_timers函数中会初始化TCP报文 pacing调度定时器。如何设置了SK_PACING_NEEDED即表示启用该功能
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

然后在__tcp_transmit_skb函数中会if (skb->len != tcp_header_size)判断,如果skb的数据长度不等于 TCP报头长度(即数据长度大于0)会调用tcp_internal_pacing->hrtimer_start函数启动高精度定时器pacing_timer。
在这里插入图片描述

在这里插入图片描述
然后在定时器回调函数中tcp_pace_kick->tcp_tsq_handler->tcp_write_xmit进行报文的发送。其中通过sk_pacing_rate设置报文的发送速率。由于此时在pacing_timer高精度定时器的回调函数中所以hrtimer_is_queued(&tcp_sk(sk)->pacing_timer)判断为假即tcp_pacing_check判断为假,进而在tcp_write_xmit函数中会最终调用tcp_transmit_skb将报文发送到ip层。

总结

1.若开启了tcp pacing功能则每次的报文发送实际是由高精度定时器pacing_timer的回调函数中进入tcp_write_xmit->tcp_transmit_skb将报文发送到ip层。若没有开启tcp pacing功能则每次tcp_write_xmit函数再判断是否使用Nagle机制进行报文的合并发送。
2.tcp最终发送报文到ip层由__tcp_transmit_skb调用err = icsk->icsk_af_ops->queue_xmit(sk, skb, &inet->cork.fl);进行发送。
3.tcp 重传定时器icsk_retransmit_timer的启动都由inet_csk_reset_xmit_timer进行设置。

  • 18
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值