日记(16)-20140928

昨天看了电影《亲爱的》,很真实。

---------------------------------------华丽分割线----------------------------------------------

好了,说说今天。

简单谈一下我对listen函数,及其背后机制的理解。  

1,内核为每个监听套接字维护2个队列:        未完成连接队列, 已完成连接队列。

2,建立三次握手后,sockfd从未完成连接队列加入已完成连接队列。

3,accept()函数不参与三次握手,而只负责从已建立连接队列中取出一个连接和本地连接 进行绑定;

4,backlog参数决定了未完成队列和已完成队列中连接数目之和的最大值

5,accept()函数调用,会从已连接队列中取出一个“连接”。  未完成队列和已完成队列中连接数目之和将减少1。

6,监听套接字的已完成队列中的元素个数大于0,那么该套接字是可读的。
7,当程序调用accept的时候(设置阻塞参数),那么判定该套接字是否可读,不可读则进入睡眠,直至已完成队列中的元素个数大于0(监听套接字可读)而唤起监听进程。

从网上找了一段验证该机制的代码:额,结果,我不能理解。。。

    #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;

        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(12989);

        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;
    }


----------------------------------------华丽分割线---------------------------------------------------

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



    //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(12989);

        int i;
        for(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...
",getpid());
                sleep(3);
                close(sockfd);
                exit(0);
            }
        }

        while(1)
        {
            cpid = wait(NULL);
            if(cpid==-1){
                perror("end of wait");
                break;
            }
            printf("pid#%d exit...
",cpid);
        }
        return 0;
    }

上部分是服务端,下部分是客户端。

服务端执行:     ./server 2

客户端执行:      ./client

执行结果:

pid#1962174 connected...
pid#1871924 connected...
pid#1146952 connected...
pid#1585294 connected...
pid#1962174 exit...
pid#1146952 exit...
pid#1871924 exit...
pid#1585294 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
connect error: Connection timed out
pid#2064532 exit...
pid#1749096 exit...
pid#1052892 exit...
pid#1077410 exit...
pid#782454 exit...
pid#1261572 exit...
pid#602162 exit...
pid#1761490 exit...
pid#1409108 exit...
pid#1687662 exit...
pid#897224 exit...
pid#1720342 exit...
pid#1765402 exit...
pid#1830952 exit...
pid#2019546 exit...
pid#2085100 exit...
end of wait: No child processes

立刻建立了4个连接。

怎么理解呢?

我的执行环节为AIX 6.1.0.0

原文地址:https://www.cnblogs.com/zhangyabin---acm/p/3998475.html