listen()函数中backlog参数分析

实例分析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;
}  

实验结果

服务器端显示:

[email protected]:~/slp/NetWrokProgram/server# ./aworker 2
new connection...
new connection...
new connection...
new connection...
new connection... 

客户端显示:

[email protected]:~/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

将server端的代码中的sleep(60)注释,即服务端listen即开始进入while循环中的accept阻塞:

...
listen(listenfd,queuelen);
sleep(60); //将这个注释,会出现另一种情况哟~~
while(1)
{
    connfd = accept(listenfd,NULL,0);
    ....  

同样的运行服务端结果如下:

[email protected]:~/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...  

客户端

[email protected]:~/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  

结果分析:

由于每个连接在建立之后,已完成队列中的连接马上就被accept给读取了,所以已完成和未完成队列中的连接数之和根本不可能超过backlog限定的个数。

转自:http://blog.csdn.net/ordeder/article/details/21551567

时间: 2024-08-29 09:38:19

listen()函数中backlog参数分析的相关文章

tcp/ip协议listen函数中backlog参数的含义

listen函数的定义如下所示: #include <sys/socket.h> int accept(int sockfd, struct sockaddr * restrict addr, socklen_t *restrict len); 返回值:若成功则返回文件(套接字)描述符,若出错则返回-1 int listen(int sockfd, int backlog);返回值:若成功则返回0:若出错则返回-1 之前看书的时候对listen函数的参数backlog不是很理解,今天看到一篇很

tcp/ip协议listen函数中backlog参数的含义与php-fpm的502 Bad Gateway

To understand the backlog argument, we must realize that for a given listening socket, the kernel maintains two queues :要明白backlog参数的含义,我们必须明白对于一个listening socket,kernel维护者两个队列: 1.An incomplete connection queue, which contains an entry for each SYN t

C++ 中获取 可变形参函数中的参数

#include <iostream> #include <stdarg.h> using namespace std; int ArgFunc(const char * str, ...) { va_list ap; // 定义参数列表变量 va_start(ap, str); // 确定参数位置,表明从 str 开始获取参数 // 开始获取参数 var_arg(ap, 数据类型) 返回获取的值 cout<<va_arg(ap, int)<<endl; c

自定义函数中的参数返回值 “-&gt; (Int -&gt; Int)”的问题

func makeIncrementer() -> (Int -> Int) { func addOne(number: Int) -> Int { return 1 + number } return addOne } var increment = makeIncrementer() println(increment(7)) 这里为什么要写两个 Int->Int 这里是返回值是参数,左边是参数,右边是返回值的意思. 自定义函数中的参数返回值 "-> (Int

python函数中的参数类型

python函数中的参数 python的函数类型详解

38 py改变函数参数的值关键字参数和参数默认值函数中可变参数将序列中的元素值作为函数对应的参数值传

第五课:改变函数参数的值 一个python函数可以有任意多个参数,在一个函数的外部来定义变量,然后把变量作为参数传入到函数内,并且在函数的内部来修改函数的参数值,函数结束之后,这些变量的值在如何变化呢? 给函数传递值有2种:1种是值传递,1种是引用传递 # 改变函数参数的值 # 值传递(数值.字符串.布尔 这些都是值传递) 在函数的内部修改变量值,不改变原参数定义的参数值,解释为: 这个在函数中不会改变原来定义(函数外部)的值 这是因为函数里面会有一个占的概念,外边的变量的值会复制给 占 里面,

TCP/IP协议中backlog参数

TCP建立连接是要进行三次握手,但是否完成三次握手后,服务器就处理(accept)呢? backlog其实是一个连接队列,在Linux内核2.2之前,backlog大小包括半连接状态和全连接状态两种队列大小. 半连接状态为:服务器处于Listen状态时收到客户端SYN报文时放入半连接队列中,即SYN queue(服务器端口状态为:SYN_RCVD). 全连接状态为:TCP的连接状态从服务器(SYN+ACK)响应客户端后,到客户端的ACK报文到达服务器之前,则一直保留在半连接状态中:当服务器接收到

TCP SOCKET中backlog参数的用途是什么? ---图解

https://www.frozentux.net/ipsysctl-tutorial/chunkyhtml/tcpvariables.html http://www.cnxct.com/something-about-phpfpm-s-backlog/ http://tech.uc.cn/?p=1790 在前年时,业务中遇到好多次因为PHP-FPM的backlog参数引发的性能问题,一直想去详细研究一番,还特意在2013年总结里提到这事<为何PHP5.5.6中fpm backlog Chang

Effective C++ .37 virtual函数中默认参数的表现

#include <iostream> #include <cstdlib> using namespace std; class Pen { public: virtual void write(int color = 0) { cout<<"write with color:"<<color<<endl; } }; class Pencil : public Pen{ public: void write(int colo