linux网络编程backlog和somaxconn | 戒修

沉迷技术的小沙弥 · · 340 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

前言

学习过的知识只要用的机会不多,多半过段时间就会忘记.如果能反复学习或者记笔记则会记得更牢固一点.以后也可以直接查看复习.

以下内容基于Linux 2.6.18内核

listen方法传入的backlog参数

#include <sys/socket.h>

int listen(int sockfd, int backlog);

在上面的代码中我们看到listen函数的第二个参数为backlog. 这个参数的意义在不同的Linux内核版本或操作系统定义是不同的.

tcp状态转化图

tcp-state-diagram.png

建立Tcp连接需要3次握手, 因此在一个连接的状态变为ESTABLISHED之前,它会有一个过渡的中间状态SYN RECEIVED
因此TCP/IP协议栈就有2种方法来实现一个处于listen状态SOCKET连接.

  1. 只使用一个队列, 也就是说未成功建立连接的和已经成功建立连接的socket都放入一个队列.但是只有处于状态ESTABLISHED的socket才能被应用程序调用accept获取.
  2. 使用2个队列, 一个队列保存处于状态SYN RECEIVED的socket, 一个队列保存已经成功建立连接的socket.在历史上BSD采用这种实现方式.

linux 上的backlog

在Linux2.2以前的版本中, backlog的值是未完成连接建立的socket队列长度. 具体描述可以参考http://man7.org/linux/man-pages/man2/listen.2.html;在后来的版本中,backlog的值就是指代已经完成连接建立, 等待accept调用的socket队列最大长度.未完成连接建立的队列最大长度可以由/proc/sys/net/ipv4/tcp_max_syn_backlog配置来控制.

已完成队列满后

通常未完成队列的长度大于已完成队列.已完成队列满后, 当服务器收到来自客户端的ACK包时如果 /proc/sys/net/ipv4/tcp_abort_on_overflow 设为 1, 直接回RST包,结束连接.否则忽视ACK包.

内核有定时器管理未完成队列,对于由于网络原因没收到ACK包或是收到ACK包后被忽视的SYN_RCVD连接重发SYN+ACK包, 最多重发次数由/proc/sys/net/ipv4/tcp_synack_retries 设定.

backlog 即上述已完成队列的大小, 这个设置是个参考值,不是精确值. 内核会做些调整, 大于/proc/sys/net/core/somaxconn, 则取somaxconn的值

未完成队列满后

如果启用syncookies (net.ipv4.tcp_syncookies = 1),新的连接不进入未完成队列,不受影响.否则,服务器不在接受新的连接.

SYN 洪水攻击(syn flood attack)

通过伪造IP向服务器发送SYN包,塞满服务器的未完成队列,服务器发送SYN+ACK包 没回复,反复SYN+ACK包,使服务器不可用.

启用syncookies 是简单有效的抵御措施.
启用syncookies,仅未完成队列满后才生效.

参考

http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
http://www.jianshu.com/p/fe2228a77429

本文来自:沉迷技术的小沙弥

感谢作者:沉迷技术的小沙弥

查看原文:linux网络编程backlog和somaxconn | 戒修

340 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传