qqwx
导航
公告
昵称:qqwx园龄:2年7个月
粉丝:5
关注:0 +加关注
统计
- 随笔 - 43
- 文章 - 0
- 评论 - 2
- 引用 - 0
常用链接
随笔分类
随笔档案
- 2017年4月 (4)
- 2017年3月 (3)
- 2017年1月 (3)
- 2016年12月 (1)
- 2016年11月 (3)
- 2016年5月 (2)
- 2016年4月 (2)
- 2016年3月 (1)
- 2015年9月 (1)
- 2015年8月 (3)
- 2011年1月 (1)
- 2010年3月 (3)
- 2010年2月 (9)
- 2010年1月 (2)
- 2009年12月 (5)
最新评论
- 1. Re:https基础流程
- 支持支持支持
- --坦荡
- 2. Re:https基础流程
- 支持支持支持
- --牛腩
阅读排行榜
- 1. linux loadavg详解(top cpu load)(2579)
- 2. 分布式入门之1:Lease机制(1130)
- 3. 分布式入门之2:Quorum机制(726)
- 4. golang的http分析(702)
- 5. 垃圾回收算法(6)三色标记(683)
评论排行榜
tcp连接listen的backlog剖析
TCP连接中,最重要的是连接TCP连接上,两个方向之间的各个状态及各个系统调用与状态之间的关系。往往可以以两种图表示,第一种是状态转换图,第二种是连接时序图。如下: 状态图:int listen(int sockfd, int backlog);
其backlog是一个建议值,用于指定内部的队列大小,以控制同时建立的连接请求数量。
针对控制连接这个需求,有两种方法实现这个backlog:- 单一队列来控制连接。队列中既包含了SYN_RCVD的状态,也包含了ESTABLISHED状态。accept只处理后面一种状态。如果三次握手中的ACK到来,则会在队列中直接改其状态。显然,这时backlog为这一队列的长度。
- 两个单独队列来控制。两种状态分别实现单独的队列。显然这种情况下,两个队列都必须有明确的大小限制,backlog只能限制其中一个。
backlog argument on TCP sockets changed with Linux 2.2. Now it specifies the queue length forcompletely established sockets waiting to be accepted,
instead of the number of incomplete connection requests. The maximum length of the queue for incomplete sockets can be set using /proc/sys/net/ipv4/tcp_max_syn_backlog. 可见,与UNP书中描述并不一致。是上述的第二种实现方法:两个队列,其中未完成队列长度限制以内核参数来表示,而已完成队列才是backlog。
cat /proc/sys/net/ipv4/tcp_max_syn_backlog 2048 具体代码: TCP收到最终ACK后,重建一个sock: tcp_v4_syn_recv_sock函数中:
1 if (sk_acceptq_is_full(sk))
2 goto exit_overflow;
3
4 newsk = tcp_create_openreq_child(sk, req, skb);
5 if (!newsk)
6 goto exit_nonewsk;
7
可见,在新生成一个socket时,先判断是否full。
static inline bool sk_acceptq_is_full(const struct sock *sk)
{
return sk->sk_ack_backlog > sk->sk_max_ack_backlog;
}
/*
* Move a socket into listening state.
*/
int inet_listen(struct socket *sock, int backlog)中:
sk->sk_max_ack_backlog = backlog;
backlog传给了sk_max_ack_backlog。可见,此backlog用作判断complete queue。
在往外层,调用处: 1 child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL,
2 req, &own_req);
3 if (!child)
4 goto listen_overflow;
5
6 sock_rps_save_rxhash(child, skb);
7 tcp_synack_rtt_meas(child, req);
8 return inet_csk_complete_hashdance(sk, child, req, own_req);
9
10 listen_overflow:
11 if (!sysctl_tcp_abort_on_overflow) {
12 inet_rsk(req)->acked = 1;
13 return NULL;
14 }
15 embryonic_reset:
16 if (!(flg & TCP_FLAG_RST)) {
17 /* Received a bad SYN pkt - for TFO We try not to reset
18 * the local connection unless it's really necessary to
19 * avoid becoming vulnerable to outside attack aiming at
20 * resetting legit local connections.
21 */
22 req->rsk_ops->send_reset(sk, skb);
23 } else if (fastopen) { /* received a valid RST pkt */
24 reqsk_fastopen_remove(sk, req, true);
25 tcp_reset(sk);
26 }
27 if (!fastopen) {
28 inet_csk_reqsk_queue_drop(sk, req);
29 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
30 }
31 return NULL;
32
可见,如果backlog满了,需要关注sysctl_tcp_abort_on_overflow,而些值是/proc下配置。 如果没有配,则啥都没干,直接忽略,这会使server端一定时间段重发SYNC/ACK。如果配置了,则走到下面发RST的流程。 另一点,客户端在发送完最后一个ACK,则进入了ESTABLISHED状态,但如上所述,这个ACK可能因为server端的backlog问题使得被忽略。但客户端并不知道,因为它是ESTABLISHED,它这段时间可以发数据!而后续重发来的SYNC/ACK,会使得客户端重发已经发出的数据,赞成带宽浪费。而TCP slow start会缓减这种情况。 backlog已满的情况下,不仅对于complete queue,对于ack queue也会有处理,适当限速(?)以丢掉一部分的sync,避免太拥堵。在函数中:
int tcp_conn_request(struct request_sock_ops *rsk_ops,
const struct tcp_request_sock_ops *af_ops,
struct sock *sk, struct sk_buff *skb)
。。。
/* Accept backlog is full. If we have already queued enough
* of warm entries in syn queue, drop request. It is better than
* clogging syn queue with openreqs with exponentially increasing
* timeout.
*/
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
goto drop;
}
总结:
- 服务端的连接建立有两个地方需要排队,一是sync包上来时,另一个是ACK上来时。对于linux来说,前者长度由配置项决定,机器上是2048;后者由listen带入的backlog指定;
- 如果backlog对应的队列满后,判断配置项,如果配了,rst,否则直接忽略,等待超时重发;
- 客户端只要发送了ACK后,即进入established状态,而服务端则要accept后。两者不对等,且客户端建立后立即可发送数据。
- sync队列也会对complete队列是否满进行参考。如果满了,限制收包速度,适当丢弃一些包。
posted on 2016-11-06 23:03 qqwx 阅读(549) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部 注册用户登录后才能发表评论,请 登录 或 注册,访问网站首页。 【推荐】超50万VC++源码: 大型组态工控、电力仿真CAD与GIS源码库!【缅怀】传奇谢幕,回顾霍金76载传奇人生
【推荐】腾讯云校园拼团福利,1核2G服务器10元/月!
【活动】2050 科技公益大会 - 年青人因科技而团聚
· 卫哲辞职:阿里巴巴史上最震撼的人事地震调查
· webOS焕发新生!LG宣布开源
· 阅文发布2017年财报,去年利润暴增14倍
· 对标Model S!奥迪A9 E-Tron纯电轿车正式宣布
· 马斯克在澳洲建了全球最大蓄电池 英国亿万富豪要建个更大的
» 更多新闻...
· 写给自学者的入门指南
· 和程序员谈恋爱
· 学会学习
· 优秀技术人的管理陷阱
· 作为一个程序员,数学对你到底有多重要
» 更多知识库文章...