• 日记(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

  • 相关阅读:
    Android源码之Gallery专题研究(2)
    Android源码之Gallery专题研究(1)
    Android UI 优化——使用HierarchyViewer工具
    如何打开USB OTG功能:
    JavaSE入门学习5:Java基础语法之keyword,标识符,凝视,常量和变量
    Multiply Strings
    android动态控制组件的位置、大小和新的动画
    linux系统编程:线程同步-信号量(semaphore)
    imx6q GPIO功能的用法
    NoSQL数据库概览及其与SQL语法的比較
  • 原文地址:https://www.cnblogs.com/zhangyabin---acm/p/3998475.html
Copyright © 2020-2023  润新知