关于 tcp syn 队列和 accept 队列

这篇文章里 说了 socket listen backlog 的意义,这里继续。

1. socket listen backlog 指定的其实就是 accept 队列,也就是 ESTABLISHED 状态的连接,这个数值不能超过 /proc/sys/net/core/somaxconn;

syn 队列里面放的是未建立的连接,数值由内核参数 /proc/sys/net/ipv4/tcp_max_syn_backlog 定义,应用代码没法修改。

 

2. 如果 accept 队列满,client 发来 ack,连接从 syn 队列移到 accept 队列的时候会发生什么呢?

1). 如果 /proc/sys/net/ipv4/tcp_abort_on_overflow 为1,会发送 RST;如果为0,则「什么都不做」,也就是「忽略」。

2). 但是,即使被忽略,对于 SYN RECEIVED 状态, 会有重试,重试次数定义在 /proc/sys/net/ipv4/tcp_synack_retries(重试时间有个算法)。

3). client 在收到 server 发来的重试 synack 之后,它认为之前发给 server 的 ack 丢失,会重发,此时如果 server 的 accept 队列有「空位」,会把连接移到 accpet 队列,并把 SYN RECEIVED 改成 ESTABLISHED。

4). 从另一个角度看, 即使 client 发的 ack 被忽略,因为 client 已经收到了 synack,client 认为连接已经建立,它可能会直接发送数据(ack 和 数据一起发送),这部分数据也会被忽略,会重传,幸好有「慢」启动机制保证重传的数据不会太多。

5). 如果 client 先等待 server 发来的数据,在 client 端连接是 ESTABLISHED,server 认为连接是 CLOSED,这会造成「半连接」。

6). 事实上,如果 accept 队列满了,内核会限制 syn 包的进入速度,如果太快,有些包会被丢弃。

 

注:本文讨论的是 Linux。

参考:

http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html

http://linux.die.net/man/2/listen

 

此条目是由wateer发表在未分类分类目录的。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已用*标注