背景知识

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个客户端与服务器建立连接,查看连接的建立情况。

服务器代码:

[cpp] view plain copy
  1. #include <stdio.h>
  2. #include<unistd.h>
  3. #include<sys/types.h>       /* basic system data types */
  4. #include<sys/socket.h>      /* basic socket definitions */
  5. #include<netinet/in.h>      /* sockaddr_in{} and other Internet defns */
  6. #include<arpa/inet.h>       /* inet(3) functions */
  7. #include<sys/epoll.h>       /* epoll function */
  8. #include<fcntl.h>
  9. #include<stdlib.h>
  10. #include<errno.h>
  11. #include<stdio.h>
  12. #include<string.h>
  13. int main(int argc,char*argv[])
  14. {
  15. int listenfd,connfd;
  16. struct sockaddr_in cliaddr,servaddr;
  17. int queuelen=5;
  18. if(argc!=2){
  19. puts("usage# ./aworker listenqueuelen");
  20. exit(0);
  21. }
  22. queuelen=atoi(argv[1]);
  23. listenfd = socket(AF_INET,SOCK_STREAM,0);
  24. bzero(&servaddr,sizeof(servaddr));
  25. servaddr.sin_family = AF_INET;
  26. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  27. servaddr.sin_port = htons(2989);
  28. bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
  29. listen(listenfd,queuelen);
  30. sleep(60); //将这个注释,会出现另一种情况哟~~
  31. while(1)
  32. {
  33. connfd = accept(listenfd,NULL,0);
  34. if(connfd == -1)
  35. {
  36. perror("accept error");
  37. continue;
  38. }
  39. puts("new connection...");
  40. }
  41. return 0;
  42. }

client代码

[cpp] view plain copy
  1. #include "client.h"
  2. //void cli_hander(int sockfd,)
  3. int main()
  4. {
  5. int sockfd;
  6. int rc;
  7. int cpid;
  8. struct sockaddr_in servaddr;
  9. bzero(&servaddr,sizeof(servaddr));
  10. servaddr.sin_family = AF_INET;
  11. inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);
  12. servaddr.sin_port = htons(2989);
  13. for(int i=0;i<20;i++)
  14. {
  15. cpid = fork();
  16. if(cpid == 0)
  17. {
  18. sockfd = socket(AF_INET,SOCK_STREAM,0);
  19. rc = connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
  20. if(rc == -1)
  21. {
  22. perror("connect error");
  23. exit(0);
  24. }
  25. printf("pid#%d connected...\n",getpid());
  26. sleep(3);
  27. close(sockfd);
  28. exit(0);
  29. }
  30. }
  31. while(1)
  32. {
  33. cpid = wait(NULL);
  34. if(cpid==-1){
  35. perror("end of wait");
  36. break;
  37. }
  38. printf("pid#%d exit...\n",cpid);
  39. }
  40. return 0;
  41. }

实验结果:

服务器端显示:

[cpp] view plain copy
  1. root@cloud2:~/slp/NetWrokProgram/server# ./aworker 2
  2. new connection...
  3. new connection...
  4. new connection...
  5. new connection...
  6. new connection...

客户端显示:

[cpp] view plain copy
  1. root@cloud2:~/slp/NetWrokProgram/client# ./a.out
  2. pid#16697 connected...
  3. pid#16699 connected...
  4. pid#16698 connected...
  5. pid#16697 exit...
  6. pid#16699 exit...
  7. pid#16698 exit...
  8. pid#16700 connected...
  9. pid#16701 connected...
  10. pid#16700 exit...
  11. pid#16701 exit...
  12. connect error: Connection timed out
  13. connect error: Connection timed out
  14. connect error: Connection timed out
  15. connect error: Connection timed out
  16. connect error: Connection timed out
  17. connect error: Connection timed out
  18. connect error: Connection timed out
  19. connect error: Connection timed out
  20. connect error: Connection timed out
  21. connect error: Connection timed out
  22. connect error: Connection timed out
  23. connect error: Connection timed out
  24. connect error: Connection timed out
  25. connect error: Connection timed out
  26. connect error: Connection timed out
  27. pid#16702 exit...
  28. pid#16703 exit...
  29. pid#16704 exit...
  30. pid#16705 exit...
  31. pid#16706 exit...
  32. pid#16707 exit...
  33. pid#16708 exit...
  34. pid#16709 exit...
  35. pid#16710 exit...
  36. pid#16711 exit...
  37. pid#16712 exit...
  38. pid#16713 exit...
  39. pid#16714 exit...
  40. pid#16715 exit...
  41. pid#16716 exit...
  42. end of wait: No child processes

结果分析:

同时建立连接的客户端进程共有20个,可是只有5个完成了连接的建立,其他15个没有成功。有趣的是,建立的5个链接中有3个是马上建立的,2个是过了一段时间后后来才建立的。

实例分析2

将server端的代码中的sleep(60)注释,即服务端listen即开始进入while循环中的accept阻塞:
[html] view plain copy
  1. ...
  2. listen(listenfd,queuelen);
  3. sleep(60); //将这个注释,会出现另一种情况哟~~
  4. while(1)
  5. {
  6. connfd = accept(listenfd,NULL,0);
  7. ....

同样的运行,结果如下:

[html] view plain copy
  1. root@cloud2:~/slp/NetWrokProgram/server# ./aworker 2
  2. new connection...
  3. new connection...
  4. new connection...
  5. new connection...
  6. new connection...
  7. new connection...
  8. new connection...
  9. new connection...
  10. new connection...
  11. new connection...
  12. new connection...
  13. new connection...
  14. new connection...
  15. new connection...
  16. new connection...
  17. new connection...
  18. new connection...
  19. new connection...
  20. new connection...
  21. new connection...

客户端:

[html] view plain copy
  1. root@cloud2:~/slp/NetWrokProgram/client# ./a.out
  2. pid#16736 connected...
  3. pid#16737 connected...
  4. pid#16738 connected...
  5. pid#16739 connected...
  6. pid#16740 connected...
  7. pid#16741 connected...
  8. pid#16742 connected...
  9. pid#16743 connected...
  10. pid#16744 connected...
  11. pid#16745 connected...
  12. pid#16746 connected...
  13. pid#16747 connected...
  14. pid#16748 connected...
  15. pid#16749 connected...
  16. pid#16750 connected...
  17. pid#16751 connected...
  18. pid#16752 connected...
  19. pid#16753 connected...
  20. pid#16755 connected...
  21. pid#16754 connected...
  22. pid#16736 exit...
  23. pid#16737 exit...
  24. pid#16738 exit...
  25. pid#16739 exit...
  26. pid#16740 exit...
  27. pid#16741 exit...
  28. pid#16742 exit...
  29. pid#16743 exit...
  30. pid#16744 exit...
  31. pid#16745 exit...
  32. pid#16746 exit...
  33. pid#16747 exit...
  34. pid#16748 exit...
  35. pid#16749 exit...
  36. pid#16750 exit...
  37. pid#16751 exit...
  38. pid#16752 exit...
  39. pid#16753 exit...
  40. pid#16755 exit...
  41. pid#16754 exit...
  42. end of wait: No child processes

结果分析:

由于每个连接在建立之后,已完成队列中的连接马上就被accept给读取了,所以已完成和未完成队列中的连接数之和根本不可能超过backlog限定的个数。
原文链接:
http://blog.csdn.net/ordeder/article/details/21551567

listen()函数中backlog参数分析相关推荐

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

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

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

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

  3. TCP之三:TCP/IP协议中backlog参数(队列参数)

    目录: <TCP洪水攻击(SYN Flood)的诊断和处理> <TCP/IP协议中backlog参数> TCP建立连接是要进行三次握手,但是否完成三次握手后,服务器就处理(ac ...

  4. libvlc_media_add_option 函数中的参数设置

    libvlc_media_add_option   函数中的参数设置 Usage: vlc [options] [stream] ... You can specify multiple stream ...

  5. 在setInterval函数中传递参数

    本文翻译自:Pass parameters in setInterval function Please advise how to pass parameters into a function c ...

  6. python函数中可变参数的传递方式是_Python中函数的参数传递与可变长参数

    1.Python中也有像C++一样的默认缺省函数 1 def foo(text,num=0):2 printtext,num3 4 foo("asd") #asd 0 5 foo( ...

  7. [SpringBoot2]ajax函数中data参数的数据设置方式

    ajax函数中data参数的数据设置方式:

  8. Pytorch中tensor维度和torch.max()函数中dim参数的理解

    Pytorch中tensor维度和torch.max()函数中dim参数的理解 维度 参考了 https://blog.csdn.net/qq_41375609/article/details/106 ...

  9. 以下是一个使用 VBA 的例子,演示了 ByVal 和 ByRef 的区别,以及如何在函数中传递参数和返回值。

    以下是一个使用 VBA 的例子,演示了 ByVal 和 ByRef 的区别,以及如何在函数中传递参数和返回值: Sub Example()Dim x As Integer, y As Integerx ...

最新文章

  1. iOS应用架构谈 组件化方案
  2. 解决Windows与虚拟机ubuntu之间相互直接拖动文件
  3. php收集radio表单,jQuery对于单选表单(radio)以及其它表单取值
  4. 远距离蓝牙四驱小车方案
  5. 编译问题二 /snmplib/tools.c:920 undefined reference to `clock_gettime' 问题解决
  6. c语言中包含math.h的时用gcc编译要加-lm参数
  7. ie11浏览器不能显示最新修改的程序,调试出现代码逻辑错误却依旧执行
  8. 初中参观机器人博物馆的作文_导览机器人为参观者带来更佳的观展体验
  9. Windows下IIS中不能添加网站
  10. 【目标跟踪】基于matlab光流法运动视频跟踪【含Matlab源码 1357期】
  11. 95%的码农都在用的编程神器,值得一看!
  12. 金万维异速联远程接入解决方案
  13. Apache开启rewrite重写模块
  14. fastqc检验时不能执行java_fastqc对原始测序reads质控
  15. XEN的启动信息输出到“Platform timer is 14.318MHz HPET”就暂停接收的解决办法
  16. 项目管理涉及到的文档
  17. 误删文件夹但是回收站没有找到怎么恢复?
  18. 【ML】Apriori算法原理及代码实现
  19. 四十三、文件传输协议FTP、电子邮件、万维网
  20. 微信消息推送 有新发现 进来看

热门文章

  1. 本月 上月 php,显示本月,上月,今天,今年以及各时间起点与
  2. 集合相等问题_JAVA
  3. Win7安装64位CentOS 6.4双系统详细过程
  4. Java中利用socket实现简单的服务端与客户端的通信(中级)——实现任意双向通信
  5. Programming Computer Vision with Python (学习笔记一)
  6. 关于错误的那点事——惨不忍睹的错误
  7. java程序员从笨鸟到菜鸟之(七)一—java数据库操作
  8. Windows API一日一练(一)第一个应用程序 使用应用程序句柄 使用命令行参数 MessageBox函数 RegisterClass和RegisterClassEx函数
  9. 回首向来萧瑟处,也无风雨也无晴~小祁的2018
  10. 第6周第4课:复习及扩展知识