isten函数的backlog参数解释
2015-11-18 10:14
246 查看
Listen函数的原型是:int listen(int socket, int backlog);此函数用于建立tcp连接时监听系统的某一个端口。
第一个参数比较好理解,是调用listen之前创建的socket的句柄,第二个参数单从名称不好理解,从linux的man资料来看的解释是tcp半连接队列的大小,至于何为半连接队列则没有做进一步说明,这里详细解释一下第二个参数backlog的含义。
说到backlog,这里先从tcp的三次握手开始说起,下图是tcp三次握手的过程图:
三次握手过程:
1. 客户端向服务器发送一个SYN置位的TCP报文,其中包含连接的初始序列号x和一个窗口大小(表示客户端上用来存储从服务器发送来的传入段的缓冲区的大小)。
2. 服务器收到客户端发送过来的SYN报文后,向客户端发送一个SYN和ACK都置位的TCP报文,其中包含它选择的初始序列号y、对客户端的序列号的确认x+1和一个窗口大小(表示服务器上用来存储从客户端发送来的传入段的缓冲区的大小)。
3. .客户端接收到服务器端返回的SYN+ACK报文后,向服务器端返回一个确认号y+1和序号x+1的ACK报文,一个标准的TCP连接完成。
从上图可以看出右边服务器的有两个状态,第一个状态是收到客户端SYNC包的状态“SYN RECD”
第二个状态是发送了SYNC + ACK之后收到客户端ACK响应包的状态”ESTABLISHED”
这两个状态是TCP连接真正建立之前的两个过度状态,当服务器同时接收来自多个客户端的连接请求时,系统会同时存在多个这样的状态,系统为了维护这些状态,需要开辟两个队列来存放这两个中间状态,一个叫“半连接队列”用来存放“SYN RECVD”状态的连接,一个叫“完整连接队列”用来存放“ESTABLISHED”状态的tcp连接。
当处于“SYN RECVD”队列的连接,收到了客户端的ACK响应包的时候,这个连接会从“SYN
RECVD”队列删除,并添加到”ESTABLISHED“队列的末尾,这两个队列大小的总和就是listen函数的backlog第二个参数来决定的。当你调用listen函数之后调用accept函数,其实是从“完整连接队列”里面取一个连接出来建立真正的tcp连接。
两个队列的总大小(backlog)在linux系统是有限制的,具体可以看cat /proc/sys/net/core/somaxconn,之前默认是128,现在系统运维的同学都已经统一做了修改,现在最大为2048,这个参数在系统内核是有做限制的,假如你设置的backlog小于等于0,系统会默认按照本身定义的最小的值来设置,假如你设置的backlog大于somaxconn定义的大小,系统会默认按照somaxconn的大小来分配半连接队列。当然了,你在启动程序之前也可以先修改一下这个系统限制:
#set somaxconn = 4096
echo 4096 > /proc/sys/net/core/somaxconn
题外话:
大家经常听到的DDOS攻击,就是通过控制大量的“僵尸“机器发送大量的tcp请求到目标服务器,但是在tcp握手的最后一步,不发送对来自服务器SYNC数据包的ACK响应包,导致大量的无效请求占满了”SYN RECVD”队列,从而导致真正有效的用户尝试建立tcp连接到服务器时,由于没有空闲的”SYN
RECVD”队列的节点而无法建立成功。
第一个参数比较好理解,是调用listen之前创建的socket的句柄,第二个参数单从名称不好理解,从linux的man资料来看的解释是tcp半连接队列的大小,至于何为半连接队列则没有做进一步说明,这里详细解释一下第二个参数backlog的含义。
说到backlog,这里先从tcp的三次握手开始说起,下图是tcp三次握手的过程图:
三次握手过程:
1. 客户端向服务器发送一个SYN置位的TCP报文,其中包含连接的初始序列号x和一个窗口大小(表示客户端上用来存储从服务器发送来的传入段的缓冲区的大小)。
2. 服务器收到客户端发送过来的SYN报文后,向客户端发送一个SYN和ACK都置位的TCP报文,其中包含它选择的初始序列号y、对客户端的序列号的确认x+1和一个窗口大小(表示服务器上用来存储从客户端发送来的传入段的缓冲区的大小)。
3. .客户端接收到服务器端返回的SYN+ACK报文后,向服务器端返回一个确认号y+1和序号x+1的ACK报文,一个标准的TCP连接完成。
从上图可以看出右边服务器的有两个状态,第一个状态是收到客户端SYNC包的状态“SYN RECD”
第二个状态是发送了SYNC + ACK之后收到客户端ACK响应包的状态”ESTABLISHED”
这两个状态是TCP连接真正建立之前的两个过度状态,当服务器同时接收来自多个客户端的连接请求时,系统会同时存在多个这样的状态,系统为了维护这些状态,需要开辟两个队列来存放这两个中间状态,一个叫“半连接队列”用来存放“SYN RECVD”状态的连接,一个叫“完整连接队列”用来存放“ESTABLISHED”状态的tcp连接。
当处于“SYN RECVD”队列的连接,收到了客户端的ACK响应包的时候,这个连接会从“SYN
RECVD”队列删除,并添加到”ESTABLISHED“队列的末尾,这两个队列大小的总和就是listen函数的backlog第二个参数来决定的。当你调用listen函数之后调用accept函数,其实是从“完整连接队列”里面取一个连接出来建立真正的tcp连接。
两个队列的总大小(backlog)在linux系统是有限制的,具体可以看cat /proc/sys/net/core/somaxconn,之前默认是128,现在系统运维的同学都已经统一做了修改,现在最大为2048,这个参数在系统内核是有做限制的,假如你设置的backlog小于等于0,系统会默认按照本身定义的最小的值来设置,假如你设置的backlog大于somaxconn定义的大小,系统会默认按照somaxconn的大小来分配半连接队列。当然了,你在启动程序之前也可以先修改一下这个系统限制:
#set somaxconn = 4096
echo 4096 > /proc/sys/net/core/somaxconn
题外话:
大家经常听到的DDOS攻击,就是通过控制大量的“僵尸“机器发送大量的tcp请求到目标服务器,但是在tcp握手的最后一步,不发送对来自服务器SYNC数据包的ACK响应包,导致大量的无效请求占满了”SYN RECVD”队列,从而导致真正有效的用户尝试建立tcp连接到服务器时,由于没有空闲的”SYN
RECVD”队列的节点而无法建立成功。
相关文章推荐
- MySQL 数据库主从复制架构
- 39-JAVA手机号中间四位替换为*
- js方法智能给url传参数
- SwipeRefreshLayout 与ListView滑动冲突的解决
- NSArray的4种遍历方式
- 获取UITextField光标位置(http://www.ithao123.cn/content-3983933.html)
- Java程序链接MySQL数据库
- python删除带特殊后缀的文件
- openstack通过qemu-guest-agent在物理机上操作虚拟机
- OC中的集合类NSSet、NSArray、NSDictionary
- The Old Man and The Sea
- win7设置防火墙允许Ping与telnet
- 线程同步 总结 内核对象
- adb 常用命令
- 联想THINKPAD E40的快捷键怎么关闭?哪些F1 F2 F3的键我需要用到 但是每次都按FN 太烦人了
- ThinkPHP3.2判断手机端访问并设置默认访问模块的方法
- mac svn
- Understanding How to Read a Userenv Log – Part 2
- POJ3414Pots(AC)
- [Swift]给类添加属性