listen()函数中backlog参数分析

Posted 烂笔头儿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于listen()函数中backlog参数分析的主要内容,如果未能解决你的问题,请参考以下文章

socket listen参数中的backlog

listen() 忽略 backlog 参数?

Netty ChannelOption参数详解

如何确定socket listen() backlog 参数的值?

listen函数里面backlog的意义以及各种情况

TCP之listen&backlog