免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 12802 | 回复: 25
打印 上一主题 下一主题

关于Linux TCP中超时重传定时器的疑问【还有点小问题】 [复制链接]

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-29 10:55 |只看该作者 |倒序浏览
许多资料中都有类似如下一段话:

When TCP sends a segment, it creates a Retransmission timer for that particular segment

似乎这里表示了每发送一个segment,都会有一个timer跟随该分段,那么对于一个高负荷的服务器而言,假定其在某个时刻发出了1000个分段,那么就分别有1000个超时重发定时器存在? 我无法理解这个实现方式。

另外,在inet_csk_reset_xmit_timer函数中有如下代码:

sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout);

显然这里是对icsk这个结构中的唯一一个重传timer进行重新设置,而这个timer显然不是仅供某个特定的segment使用的,所以到底该如何理解超时重传定时器呢?

另外,在TCPIP协议详解中,21.2节中,Steven给出的超时重传定时器的例子恰恰是只有一个外出分段的示例,所以我仍然不得其解

因为tcp太复杂,我一时无法全部找到对应定时器的相关其他关键代码,所以就想请各位帮助解答下。

-------------------------------------------------
PS:我稍微进一步具体描述下我的问题
-------------------------------------------------

1、发送方假设连续发送了S1,S2,S3这3个分段,那么这个icsk->icsk_retransmit_timer到底如何工作以控制这3个分段可能出现的超时?
>> 我自己的理解是因为有一个500ms的TCP定时器存在,所以每隔500ms到时一次,在这个到时中将检查刚才发出去的3个分段的时间戳是否与当前时间值有足够的间隙,如果是就表示超时出现了,于是重发对应超时的那个分段,但是这样理解就有一个问题存在,即每个发出的分段就无所谓对应的重传定时器存在了,那么之前说的icsk->icsk_retransmit_timer还有什么作用呢? 我彻底有点晕了

[ 本帖最后由 jiufei19 于 2009-9-30 16:19 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-09-29 11:20 |只看该作者
原帖由 jiufei19 于 2009-9-29 10:55 发表
许多资料中都有类似如下一段话:

When TCP sends a segment, it creates a Retransmission timer for that particular segment

似乎这里表示了每发送一个segment,都会有一个timer跟随该分段,那么对于一 ...


代码没看过,但是我记得好像tcp/ip详解还是unp讲过,实际中不会为每个tcp包设定一个计时器
所有tcp包只有一个计时器,具体怎么做的记不请了。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
3 [报告]
发表于 2009-09-29 12:18 |只看该作者

回复 #2 peimichael 的帖子

我查了下Linux的tcp代码,其中有如下函数对3个定时器分别进行了设置,显然代码表示和重传有关的定时器就只有一个,而不是每个分段对应一个

  259 void inet_csk_init_xmit_timers(struct sock *sk,
  260                    void (*retransmit_handler)(unsigned long),
  261                    void (*delack_handler)(unsigned long),
  262                    void (*keepalive_handler)(unsigned long))
  263 {   
  264     struct inet_connection_sock *icsk = inet_csk(sk);
  265     
  266     init_timer(&icsk->icsk_retransmit_timer);
  267     init_timer(&icsk->icsk_delack_timer);
  268     init_timer(&sk->sk_timer);

  269     
  270    icsk->icsk_retransmit_timer.function = retransmit_handler;  
  271     icsk->icsk_delack_timer.function     = delack_handler;
  272     sk->sk_timer.function            = keepalive_handler;
  273     
  274     icsk->icsk_retransmit_timer.data =
  275         icsk->icsk_delack_timer.data =
  276             sk->sk_timer.data  = (unsigned long)sk;
  277
  278     icsk->icsk_pending = icsk->icsk_ack.pending = 0;
  279 }

论坛徽章:
0
4 [报告]
发表于 2009-09-29 13:09 |只看该作者

回复 #3 jiufei19 的帖子

static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb)
{                              
        struct tcp_sock *tp = tcp_sk(sk);
        unsigned int prior_packets = tp->packets_out;
                                
        tcp_advance_send_head(sk, skb);
        tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
               
        /* Don't override Nagle indefinately with F-RTO */
        if (tp->frto_counter == 2)
                tp->frto_counter = 3;

        tp->packets_out += tcp_skb_pcount(skb);
        if (!prior_packets)
                inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
                                          inet_csk(sk)->icsk_rto, TCP_RTO_MAX);
}

一般情况下,Linux TCP只会在发送当前窗口的第一个包的时候,reset retrans timer。
packet_out是当前snd_wnd内发送的包的个数。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
5 [报告]
发表于 2009-09-29 13:21 |只看该作者

回复 #4 eexplorer 的帖子

请问eexplorer,那么当在一个窗口中发送方假设连续发送了S1, S2, S3共3个分段后,若S1是当前窗口的首个分段,则根据你刚才的解释,则将会重设重传定时器,并且我们再次假定S1正确到达接收方,并且接收方以ACK进行了确认,但是S2丢失了,那么这个重传定时器工作的原理大体是怎样的呢?换句话讲,icsk->icsk_retransmit_timer是如何控制这个S2是否到时的呢?

论坛徽章:
0
6 [报告]
发表于 2009-09-29 13:33 |只看该作者

回复 #5 jiufei19 的帖子

如果连续发送了发送了3个segment的话,那么packets_out != 0,那么在发S2,S3的时候,我们就不会去reset这个timer,如果S2丢失的话,packet_outs是不会减到0(因为没有收到S2的ACK),那么这个timer最后总会timeout的。而这三个segment又是差不多同时发送的,所以这个timeout value对S2来说也是正确的。

如果你先发了S1, 等收到ack后再发S2的话,那么retrans timer就会在发S1和S2的时候都会被设置。因为收到S1的ack后,packet_out会减为0。下一个S2的话,又是下一个窗口的第一个包了。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
7 [报告]
发表于 2009-09-29 14:04 |只看该作者
>> 那么这个timer最后总会timeout的。而这三个segment又是差不多同时发送的,所以这个timeout value对S2来说也
>> 是正确的
请问eexplorer,根据你的描述,是否可以这样说,对于S2来讲,假定S1正确收到后,则对于S2来讲,其实仍然使用的是S1发出那个时刻所设置的timeout时间,如果S2丢失的话,这个时间当然会超时的。进一步讲,如果在一个窗口中发出了N个分段,那么其实这N个分段都是用的同一个超时时间timeout,即首个分段发出时设置的timeout?

我的理解正确吗?

论坛徽章:
0
8 [报告]
发表于 2009-09-29 14:20 |只看该作者

回复 #4 eexplorer 的帖子

packets_out应该解释为未接受到应答的报文的数量,这样就比较好解释了

论坛徽章:
0
9 [报告]
发表于 2009-09-29 14:35 |只看该作者

回复 #8 CUDev 的帖子

谢谢指正,再确切一点就是,在当前窗口,已经发送但是还没有收到ACK的segments

论坛徽章:
0
10 [报告]
发表于 2009-09-29 14:36 |只看该作者

回复 #7 jiufei19 的帖子

是的,在正常的情况下,只有在tcp_event_new_data_sent里当packets_out = 0的时候,会reset retrans timer.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP