listen()函数中backlog参数分析
背景知识
Unix网络编程描述如下:
总结
0. accept()函数不参与三次握手,而只负责从已建立连接队列中取出一个连接和sockfd进行绑定;
1. backlog参数决定了未完成队列和已完成队列中连接数目之和的最大值(从内核角度看,是否这个和就是等于sock->recv_queue ?);
2. accept()函数调用,会从已连接队列中取出一个“连接”(可以是一个描述连接的数据结构,listensocket->sock->recv_queue[sk_buff] ? ),未完成队列和已完成队列中连接数目 之和将减少1;即accept将监听套接字对应的sock的接收队列中的已建立连接的sk_buff取下(从该sk_buff中可以获得对端主机的发送过来的tcp/ip数据包)
3. 监听套接字的已完成队列中的元素个数大于0,那么该套接字是可读的。
4. 当程序调用accept的时候(设置阻塞参数),那么判定该套接字是否可读,不可读则进入睡眠,直至已完成队列中的元素个数大于0(监听套接字可读)而唤起监听进程。
实例分析1
将服务器端的listen函数backlog设置为2,用20个客户端与服务器建立连接,查看连接的建立情况。
服务器代码:
- #include <stdio.h>
- #include<unistd.h>
- #include<sys/types.h> /* basic system data types */
- #include<sys/socket.h> /* basic socket definitions */
- #include<netinet/in.h> /* sockaddr_in{} and other Internet defns */
- #include<arpa/inet.h> /* inet(3) functions */
- #include<sys/epoll.h> /* epoll function */
- #include<fcntl.h>
- #include<stdlib.h>
- #include<errno.h>
- #include<stdio.h>
- #include<string.h>
- int main(int argc,char*argv[])
- {
- int listenfd,connfd;
- struct sockaddr_in cliaddr,servaddr;
- int queuelen=5;
- if(argc!=2){
- puts("usage# ./aworker listenqueuelen");
- exit(0);
- }
- queuelen=atoi(argv[1]);
- listenfd = socket(AF_INET,SOCK_STREAM,0);
- bzero(&servaddr,sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(2989);
- bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
- listen(listenfd,queuelen);
- sleep(60); //将这个注释,会出现另一种情况哟~~
- while(1)
- {
- connfd = accept(listenfd,NULL,0);
- if(connfd == -1)
- {
- perror("accept error");
- continue;
- }
- puts("new connection...");
- }
- return 0;
- }
client代码
- #include "client.h"
- //void cli_hander(int sockfd,)
- int main()
- {
- int sockfd;
- int rc;
- int cpid;
- struct sockaddr_in servaddr;
- bzero(&servaddr,sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);
- servaddr.sin_port = htons(2989);
- for(int i=0;i<20;i++)
- {
- cpid = fork();
- if(cpid == 0)
- {
- sockfd = socket(AF_INET,SOCK_STREAM,0);
- rc = connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
- if(rc == -1)
- {
- perror("connect error");
- exit(0);
- }
- printf("pid#%d connected...\n",getpid());
- sleep(3);
- close(sockfd);
- exit(0);
- }
- }
- while(1)
- {
- cpid = wait(NULL);
- if(cpid==-1){
- perror("end of wait");
- break;
- }
- printf("pid#%d exit...\n",cpid);
- }
- return 0;
- }
实验结果:
服务器端显示:
- root@cloud2:~/slp/NetWrokProgram/server# ./aworker 2
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
客户端显示:
- root@cloud2:~/slp/NetWrokProgram/client# ./a.out
- pid#16697 connected...
- pid#16699 connected...
- pid#16698 connected...
- pid#16697 exit...
- pid#16699 exit...
- pid#16698 exit...
- pid#16700 connected...
- pid#16701 connected...
- pid#16700 exit...
- pid#16701 exit...
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- connect error: Connection timed out
- pid#16702 exit...
- pid#16703 exit...
- pid#16704 exit...
- pid#16705 exit...
- pid#16706 exit...
- pid#16707 exit...
- pid#16708 exit...
- pid#16709 exit...
- pid#16710 exit...
- pid#16711 exit...
- pid#16712 exit...
- pid#16713 exit...
- pid#16714 exit...
- pid#16715 exit...
- pid#16716 exit...
- end of wait: No child processes
结果分析:
同时建立连接的客户端进程共有20个,可是只有5个完成了连接的建立,其他15个没有成功。有趣的是,建立的5个链接中有3个是马上建立的,2个是过了一段时间后后来才建立的。
实例分析2
- ...
- listen(listenfd,queuelen);
- sleep(60); //将这个注释,会出现另一种情况哟~~
- while(1)
- {
- connfd = accept(listenfd,NULL,0);
- ....
同样的运行,结果如下:
- root@cloud2:~/slp/NetWrokProgram/server# ./aworker 2
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
- new connection...
客户端:
- root@cloud2:~/slp/NetWrokProgram/client# ./a.out
- pid#16736 connected...
- pid#16737 connected...
- pid#16738 connected...
- pid#16739 connected...
- pid#16740 connected...
- pid#16741 connected...
- pid#16742 connected...
- pid#16743 connected...
- pid#16744 connected...
- pid#16745 connected...
- pid#16746 connected...
- pid#16747 connected...
- pid#16748 connected...
- pid#16749 connected...
- pid#16750 connected...
- pid#16751 connected...
- pid#16752 connected...
- pid#16753 connected...
- pid#16755 connected...
- pid#16754 connected...
- pid#16736 exit...
- pid#16737 exit...
- pid#16738 exit...
- pid#16739 exit...
- pid#16740 exit...
- pid#16741 exit...
- pid#16742 exit...
- pid#16743 exit...
- pid#16744 exit...
- pid#16745 exit...
- pid#16746 exit...
- pid#16747 exit...
- pid#16748 exit...
- pid#16749 exit...
- pid#16750 exit...
- pid#16751 exit...
- pid#16752 exit...
- pid#16753 exit...
- pid#16755 exit...
- pid#16754 exit...
- end of wait: No child processes
结果分析:
listen()函数中backlog参数分析相关推荐
- listen函数的第二个参数_signal(SIGPIPE,?SIG_IGN)listen函数中backlog参数分析
signal(SIGPIPE, SIG_IGN); TCP是全双工的信道, 可以看作两条单工信道, TCP连接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道, 但本端 ...
- Linux中listen()系统调用的backlog参数分析
这篇文章是对上一篇博客网络编程常用接口的内核实现----sys_listen()的补充,上篇文章中我说listen()系统调用的backlog参数既是连接队列的长度,也指定了半连接队列的长度(不能说等 ...
- TCP之三:TCP/IP协议中backlog参数(队列参数)
目录: <TCP洪水攻击(SYN Flood)的诊断和处理> <TCP/IP协议中backlog参数> TCP建立连接是要进行三次握手,但是否完成三次握手后,服务器就处理(ac ...
- libvlc_media_add_option 函数中的参数设置
libvlc_media_add_option 函数中的参数设置 Usage: vlc [options] [stream] ... You can specify multiple stream ...
- 在setInterval函数中传递参数
本文翻译自:Pass parameters in setInterval function Please advise how to pass parameters into a function c ...
- python函数中可变参数的传递方式是_Python中函数的参数传递与可变长参数
1.Python中也有像C++一样的默认缺省函数 1 def foo(text,num=0):2 printtext,num3 4 foo("asd") #asd 0 5 foo( ...
- [SpringBoot2]ajax函数中data参数的数据设置方式
ajax函数中data参数的数据设置方式:
- Pytorch中tensor维度和torch.max()函数中dim参数的理解
Pytorch中tensor维度和torch.max()函数中dim参数的理解 维度 参考了 https://blog.csdn.net/qq_41375609/article/details/106 ...
- 以下是一个使用 VBA 的例子,演示了 ByVal 和 ByRef 的区别,以及如何在函数中传递参数和返回值。
以下是一个使用 VBA 的例子,演示了 ByVal 和 ByRef 的区别,以及如何在函数中传递参数和返回值: Sub Example()Dim x As Integer, y As Integerx ...
最新文章
- iOS应用架构谈 组件化方案
- 解决Windows与虚拟机ubuntu之间相互直接拖动文件
- php收集radio表单,jQuery对于单选表单(radio)以及其它表单取值
- 远距离蓝牙四驱小车方案
- 编译问题二 /snmplib/tools.c:920 undefined reference to `clock_gettime' 问题解决
- c语言中包含math.h的时用gcc编译要加-lm参数
- ie11浏览器不能显示最新修改的程序,调试出现代码逻辑错误却依旧执行
- 初中参观机器人博物馆的作文_导览机器人为参观者带来更佳的观展体验
- Windows下IIS中不能添加网站
- 【目标跟踪】基于matlab光流法运动视频跟踪【含Matlab源码 1357期】
- 95%的码农都在用的编程神器,值得一看!
- 金万维异速联远程接入解决方案
- Apache开启rewrite重写模块
- fastqc检验时不能执行java_fastqc对原始测序reads质控
- XEN的启动信息输出到“Platform timer is 14.318MHz HPET”就暂停接收的解决办法
- 项目管理涉及到的文档
- 误删文件夹但是回收站没有找到怎么恢复?
- 【ML】Apriori算法原理及代码实现
- 四十三、文件传输协议FTP、电子邮件、万维网
- 微信消息推送 有新发现 进来看
热门文章
- 本月 上月 php,显示本月,上月,今天,今年以及各时间起点与
- 集合相等问题_JAVA
- Win7安装64位CentOS 6.4双系统详细过程
- Java中利用socket实现简单的服务端与客户端的通信(中级)——实现任意双向通信
- Programming Computer Vision with Python (学习笔记一)
- 关于错误的那点事——惨不忍睹的错误
- java程序员从笨鸟到菜鸟之(七)一—java数据库操作
- Windows API一日一练(一)第一个应用程序 使用应用程序句柄 使用命令行参数 MessageBox函数 RegisterClass和RegisterClassEx函数
- 回首向来萧瑟处,也无风雨也无晴~小祁的2018
- 第6周第4课:复习及扩展知识