1. 程式人生 > >listen()函數中backlog參數分析

listen()函數中backlog參數分析

accep nis nbsp str .... basic and 分析 col

實例分析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

將server端的代碼中的sleep(60)註釋,即服務端listen即開始進入while循環中的accept阻塞:

...  
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...  

客戶端

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  
結果分析: 由於每個連接在建立之後,已完成隊列中的連接馬上就被accept給讀取了,所以已完成和未完成隊列中的連接數之和根本不可能超過backlog限定的個數。

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

listen()函數中backlog參數分析