Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
接收器的延迟ACK与发送器的RTO_C_Linux_Sockets_Tcp - Fatal编程技术网

接收器的延迟ACK与发送器的RTO

接收器的延迟ACK与发送器的RTO,c,linux,sockets,tcp,C,Linux,Sockets,Tcp,如果H1打开与H2的TCP连接,则H1向H2发送一个小数据包(ato延迟确认超时间隔的行为。当 连接启动,我们希望尽快确认。这个 问题是“好的”TCP在数据开始时启动缓慢 传输这意味着在我们发送前几次确认之前 发送方将坐在他这边,只对他的大部分数据排队,因为 他在任何给定时间只能发送snd_cwnd未经确认的数据包。对于 我们发送的每一个ACK,他都会增加snd_cwnd,并传输更多的信息 排队-达维姆 static void tcp\u event\u data\u recv(struct s

如果H1打开与H2的TCP连接,则H1向H2发送一个小数据包( TCP如何确保H1的RTO计时器在收到延迟的ACK之前不会过期


Linux默认的最小RTO为200ms,这理解正确吗?因此,如果网络速度很快(RTO保持在最小200ms),并且数据包在从H1到H2的过程中丢失,那么H1将在200ms后重试?如果网络速度慢,那么H1的等待时间可能远远超过200ms?

关于延迟的ACK定时,RFC 1122说:

TCP应该实现延迟的ACK,但ACK不应该实现 拖得太久,;特别是,必须避免延误 小于0.5秒,且在全尺寸流中 至少每秒钟应该有一次确认 部分

因此,这取决于实现,当然也取决于是否可能降低应用程序性能。
在linux内核中,它们不会按计时器或固定时间间隔发送延迟的ACK,正如您在下面的代码中看到的,它们的行为因条件而异。 正如您在
net/ipv4/tcp\u input.c
中看到的,他们在评论中说:

当你分析这个问题时,有一点你必须牢记在心 tp->ato延迟确认超时间隔的行为。当 连接启动,我们希望尽快确认。这个 问题是“好的”TCP在数据开始时启动缓慢 传输这意味着在我们发送前几次确认之前 发送方将坐在他这边,只对他的大部分数据排队,因为 他在任何给定时间只能发送snd_cwnd未经确认的数据包。对于 我们发送的每一个ACK,他都会增加snd_cwnd,并传输更多的信息 排队-达维姆

static void tcp\u event\u data\u recv(struct sock*sk,struct sk\u buff*skb)
{
结构tcp_sock*tp=tcp_sk(sk);
结构inet\u连接\u sock*icsk=inet\u csk(sk);
u32现在;
inet_csk_进度确认(sk);
tcp_测量_rcv_mss(sk、skb);
tcp_rcv_rtt_测量(tp);
现在=tcp\u时间戳;
如果(!icsk->icsk_确认ato){
/*接收到的第一个数据包,初始化
*延迟确认引擎。
*/
tcp_incr_quickack(sk);
icsk->icsk_ack.ato=TCP_ato_MIN;
}否则{
int m=now-icsk->icsk_ack.lrcvtime;
如果(m icsk_ack.ato=(icsk->icsk_ack.ato>>1)+TCP_ato_MIN/2;
}否则如果(micsk确认ato){
icsk->icsk_ack.ato=(icsk->icsk_ack.ato>>1)+m;
如果(icsk->icsk_ack.ato>icsk->icsk_rto)
icsk->icsk_ack.ato=icsk->icsk_rto;
}否则如果(m>icsk->icsk\U rto){
/*间隔太长。显然发件人未能
*重新启动窗口,以便快速发送确认。
*/
tcp_incr_quickack(sk);
sk_mem_reclain(sk);
}
}
icsk->icsk_ack.lrcvtime=now;
tcp检查(tp、skb);
如果(skb->len>=128)
tcp_生长_窗口(sk、skb);
}

嗯,实现是linux(最新内核)。是的,我读过RFC。你想知道linux内核中实现的具体价值吗?我添加了一些来自linux内核的注释和代码,希望它们能帮助你。谢谢。但是发送方的行为是什么?如果没有来自接收方的ack,在重新发送之前要等待多长时间?整个rto?这是TCP的输入行为,如果是的话如果您想查看
net/ipv4/tcp\u output.c
,我想您可以在那里找到答案
static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb)
{
    struct tcp_sock *tp = tcp_sk(sk);
    struct inet_connection_sock *icsk = inet_csk(sk);
    u32 now;

    inet_csk_schedule_ack(sk);

    tcp_measure_rcv_mss(sk, skb);

    tcp_rcv_rtt_measure(tp);

    now = tcp_time_stamp;

    if (!icsk->icsk_ack.ato) {
        /* The _first_ data packet received, initialize
         * delayed ACK engine.
         */
        tcp_incr_quickack(sk);
        icsk->icsk_ack.ato = TCP_ATO_MIN;
    } else {
        int m = now - icsk->icsk_ack.lrcvtime;

        if (m <= TCP_ATO_MIN / 2) {
            /* The fastest case is the first. */
            icsk->icsk_ack.ato = (icsk->icsk_ack.ato >> 1) + TCP_ATO_MIN / 2;
        } else if (m < icsk->icsk_ack.ato) {
            icsk->icsk_ack.ato = (icsk->icsk_ack.ato >> 1) + m;
            if (icsk->icsk_ack.ato > icsk->icsk_rto)
                icsk->icsk_ack.ato = icsk->icsk_rto;
        } else if (m > icsk->icsk_rto) {
            /* Too long gap. Apparently sender failed to
             * restart window, so that we send ACKs quickly.
             */
            tcp_incr_quickack(sk);
            sk_mem_reclaim(sk);
        }
    }
    icsk->icsk_ack.lrcvtime = now;

    tcp_ecn_check_ce(tp, skb);

    if (skb->len >= 128)
        tcp_grow_window(sk, skb);
}