#include <sys/types.h>
#include <sys/socket.h>
int listen(int fd, int backlog);

listen在服务器端的作用就是将服务器端的套接字文件描述符转换成被动监听的描述符,何为被动监听?

在服务端,我们的端口和ip肯定是众所周知的,我们需要调用listen来将服务端socket套接字描述符设置为被动监听外界的连接才可以实现服务端的业务.相当于让服务端处于"守株待兔"的状态,客户端是即将撞树的"兔子".

在讨论backlog之前,我们再来重述一遍TCP三次握手的过程及状态转换,因为他真的很重要!!!

  • 服务器运行开启被动监听,客户端要与服务端建立新连接的时,先发送一个syn包,进入到syn_sent状态(表示syn已经发了,sent为send的过去式嘛~~);

  • 然后服务器收到syn包后,进入到syn_rcvd状态,并回复对端一个syn包和一个ack包,;

  • 客户端收到请求数据包后,进入到established状态,三次握手完成;

对于客户端这只主动"撞到树上"的"兔子",服务器是怎样有序处理的呢?

在UNP上有讲在以前tcp怎样处理新连接请求的,我在文章中只描述现在tcp服务端处理连接请求的方式!

现在,服务器在listen时会维护两个队列,一个是处于established状态的队列即完成三次握手的队列,另一个是服务端收到客户端syn包后的队列,也就是以上讲的服务端进入syn_rcvd状态的队列,这两个队列中存的是什么?以及两个队列又有什么联系呢?

这两个队列中存的就是每个客户端的IP和端口相关信息!

说到两个队列之间联系,那么backlog的故事根据UNP上所述,backlog在之前定义的是处于listen的syn_rcvd状态和established状态下的两个用户连接队列长度之和的最大值(这句话是多余的可以选择忽略),现在表示的是完成三次握手即处于established状态的用户连接队列的长度,就通过listen第二个参数指定.

以下是示意图:

ubuntu18.10中上SYN_RCVD状态的队列的最大长度查看  cat /proc/sys/net/ipv4/tcp_max_syn_backlogESTABLISHED状态的最大长度查看    cat /proc/sys/net/core/somaxconn

当backlog值设置的比系统中定义的值大时,就使用系统定义的值.当然我们也可以修改系统中定义的值.

当我将backlog值将以下服务器backlog值设置为5的时候:

//相关头文件省略
//创建服务器端socket的类
#pragma once
class sockfd{private :static sockfd* sock ;public :struct sockaddr_in serv ;int fd ; sockfd() ; ~sockfd() ; static sockfd* getsockfd( char* ip, char* port ) ;//设置非阻塞void s_bind() ;void s_listen() ;};sockfd* sockfd:: sock = NULL ;sockfd :: sockfd()
{sock = NULL ;
}sockfd* sockfd :: getsockfd( char* ip, char* port )
{if(sock == NULL ){sock = new sockfd() ;sock->fd = socket( AF_INET, SOCK_STREAM, 0) ;int flag = 1 ;int ret = setsockopt( sock->fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag) ) ; if( ret < 0 ){free(sock) ;cout << "build socketopt error!" << endl ;exit( 1 ) ;}cout << sock->fd <<endl ;if( sock->fd < 0 ){free(sock) ;cout << "build socket error!" << endl ;exit( 1 ) ;}( sock->serv ).sin_family = AF_INET ; ( sock->serv ).sin_port = htons( atoi(port) ) ;( sock->serv ).sin_addr.s_addr = inet_addr( ip );memset(sock->serv.sin_zero,'\0',8);}return sock ;
}void sockfd :: s_bind()
{int ret = bind( sock->fd, ( struct sockaddr* )&serv, sizeof( serv ) ) ;if( ret < 0 ){   free( sock ) ;cout << "bind socket error!" << endl ;exit( 1 ) ;}cout << "binded......" << endl ;
}void sockfd :: s_listen(){//设置backlog为5int ret = listen( sock->fd , 5) ;if( ret < 0 ){free(sock) ;cout << "listen socket error!" << endl ;exit( 1 ) ;}cout << "listen......" << endl ;
}sockfd :: ~sockfd()
{close( fd ) ;free( sock ) ;sock = NULL ;
}//
//服务器程序
typedef void (*sighandler_t)(int) ;sockfd* sock = NULL ;
void sig_handle( int signo )
{if( signo == SIGINT ){delete sock ;  exit(0) ;}
}int main(int argc,char** argv)
{if( argc!=3 ){cout <<"NAME:" << argv[0] << "IP:"<<argv[1]<<"PORT:"<< argv[2] <<endl ;exit(1);}sock = sockfd::getsockfd(argv[1], argv[2]) ;sock->s_bind() ;sock->s_listen() ;int connfd ;if((connfd = accept(sock->fd, NULL, NULL)) < 0){cout << connfd << "--------------" << endl ;cout << "accept error!" << endl ;exit(1) ;}char buf[20] = "hello client!" ;send(connfd, buf, 20, 0) ;//接收信号,创建子进程重启服务器while(1){signal( SIGINT, sig_handle ) ;}
}
//执行服务器程序
./server 127.0.0.1 2345开终端并执行9次
telnet 127.0.0.1 2345//检查端口2345的tcp网络连接情况
netstat -t|grep 2345

效果如下:

可见当backlog为5时,处于established状态的已完成连接队列长度为7,参考UNP,源自Berkerly的实现给backlog值设置一个模糊因子,把它乘1.5后为未被处理队列的最大长度,所以当backlog为5时,未被处理队列的长度最大不超过8.下面是我将backlog值设置为10时,开启15个连接,有12个处于已完成队列中,三个处于未完成队列中,我的ubuntu18.10已连接对列长度为12,如图:

所以可以说该队列的长度总是大于backlog真实值,小于backlog乘上1.5的值.

至于其他多余的客户端连接在服务端还处于syn_rcvd状态的未完成连接队列中,改队列在系统中的长度为256,可以使用前面所述的方法查看自己系统的默认未完成队列最大长度.(在图中显示的是客户端连接处于syn_sent状态,服务端处于syn_rcvd状态).
那么思考一个问题…

要是syn_rcvd和established状态下listen维护的两个队列满了的话,服务器该如何处理过来的请求呢?

参考UNP上所述,TCP选择忽略该分节,客户端在syn_rcvd队列没满之前一直会发送syn请求尝试连接服务器.UNP上描述说服务器只是简单忽略,也不会发送RST分节的原因是,要是服务器发送RST分节回复该响应的话,会导致客户端不能确定所连接端口是没有服务还syn_rcvd队列已满!想了想这样挺合理!!!

参考博客:

https://www.cnblogs.com/shihuvini/p/9648377.html

https://blog.csdn.net/wenqian1991/article/details/46712041

listen的backlog值分析相关推荐

  1. Linux中listen()系统调用的backlog参数分析

    这篇文章是对上一篇博客网络编程常用接口的内核实现----sys_listen()的补充,上篇文章中我说listen()系统调用的backlog参数既是连接队列的长度,也指定了半连接队列的长度(不能说等 ...

  2. listen()函数中backlog参数分析

    背景知识 Unix网络编程描述如下: 总结 0. accept()函数不参与三次握手,而只负责从已建立连接队列中取出一个连接和sockfd进行绑定: 1. backlog参数决定了未完成队列和已完成队 ...

  3. listen函数的第二个参数_signal(SIGPIPE,?SIG_IGN)listen函数中backlog参数分析

    signal(SIGPIPE, SIG_IGN); TCP是全双工的信道, 可以看作两条单工信道, TCP连接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道, 但本端 ...

  4. 深入探索 Linux listen() 函数 backlog 的含义

    1:listen()回顾以及问题引入 2:正确的解释 3:实验验证 1:listen()回顾以及问题引入 listen()函数是网络编程中用来使服务器端开始监听端口的系统调用,首先来回顾下listen ...

  5. linux网络编程中listen函数 backlog的含义

    结论: backlog 是用来指定在TCP连接时,同时进行 3次握手建立连接的客户端数量 listen函数在一般在调用bind之后-调用accept之前调用, 它的函数原型是: #include< ...

  6. 项目经理案头手册学习系列【12】——使用挣值分析法控制项目

    1.项目控制中差异分析或挣值分析的应用 差异:与计划的任何偏差. 差异分析能够让项目经理确定项目出现的"麻烦点"并采取纠正措施. 项目经理要控制项目的四个领域:绩效目标.成本目标. ...

  7. 【Groovy】集合遍历 ( 使用 for 循环遍历集合 | 使用集合的 each 方法遍历集合 | 集合的 each 方法返回值分析 )

    文章目录 一.使用 for 循环遍历集合 二.使用 each 方法遍历集合 三.集合的 each 方法返回值分析 四.完整代码示例 一.使用 for 循环遍历集合 使用 for 循环 , 遍历集合 , ...

  8. 【Windows 逆向】OD 调试器工具 ( 分析 OD 硬件断点处的关键代码 | 添加硬件断点 | 关键代码 | MOV 指令 | EAX 寄存器值分析 | 使用命令查看 esi+0cc 地址 )

    文章目录 一.添加硬件断点 二.关键代码 三.MOV 汇编指令格式 四.EAX 寄存器值分析 五.使用命令查看 esi+0cc 地址 一.添加硬件断点 在上一篇博客中 , 在子弹个数数据内存地址 07 ...

  9. python彩票预测与分析_130期柳无尘双色球预测奖号:红球和值分析

    福彩双色球第2020129期开出奖号:01.02.05.15.28.33+04,其中红球奖号大小比开出2:4,奇偶比开出4:2,和值开出84 .蓝球为小号.偶数. 柳无尘福彩双色球第2020130期红 ...

最新文章

  1. 网站建设PHP中mysql和mysqli的区别
  2. 关于ssh的一些问题
  3. 改动office outlook 2007默认文件夹的存放位置
  4. application配置mysql_配置 SQL Server 和 MySQL Application 数据库以供租户使用
  5. java的双亲委派_深入理解Java的类加载器及双亲委派机制
  6. Layui判断Tab栏是否打开,查找Tab栏中的元素
  7. Django 点击刷新验证码
  8. Blender的常用快捷键,学习必备
  9. Transaction使用及原理
  10. 利用谷歌安全令牌(google authenticator)为服务器ssh添加二次验证功能
  11. 工程师总结:PCB设计中降低噪声与电磁干扰的方法
  12. 2015年换工作感想
  13. pandas系列学习(七):数据透视表
  14. Mybatis批量插入数据到Oracel
  15. java jtable 复选框_java swing如何在JTable一个单元格添加多个复选框
  16. 含LOB的表实际容量计算方法
  17. 第一章:pycharm、anaconda、opencv、pytorch、tensorflow、paddlex等环境配置大全总结【图像处理py版本】
  18. 全新蚂蚁L7,1台更强于19台L3+
  19. 英雄远征Erlang源码分析(9)-战斗流程解析
  20. ABB.RobotWare数据包 下载分享

热门文章

  1. ✨英语学习|如何高效做英语阅读笔记
  2. 上海应届生落户政策计算机水平,2019年上海应届生落户的加分细则,上海的同学们必看!...
  3. Jmeter学习-BeanShell 内置变量vars、props、prev
  4. 加速火狐(firefox)浏览器
  5. IE 10 SCRIPT5022: InvalidCharacterError错误解决办法
  6. CellID 基站定位
  7. 同指数幂相减公式_同底指数加减运算法则
  8. 视频数据集下载及处理
  9. Django框架学习
  10. “优必选“杯2021中国机器人技能大赛--赛后总结