• select -贾文龙


    select(09嵌入式-贾文龙-注释

    /* server.c */
    #include
    #include
    #include
    #include
    #include "wrap.c"

    #define MAXLINE 80
    #define SERV_PORT 8000

    int main(int argc, char **argv)
    {
           
    int i, maxi, maxfd, listenfd, connfd, sockfd;
           
    int nready, client[FD_SETSIZE];
            ssize_t n
    ;
            fd_set rset
    , allset;
           
    char buf[MAXLINE];
           
    char str[INET_ADDRSTRLEN];//宏定义INET_ADDRSTRLEN用于保存网络二进制地址转换为点分十进制地址
            socklen_t cliaddr_len
    ;
           
    struct sockaddr_in      cliaddr, servaddr;

            listenfd
    = Socket(AF_INET, SOCK_STREAM, 0);//打开一个网络通讯端口

            bzero
    (&servaddr, sizeof(servaddr));//初始化 servaddr 将整个结构体清零
            servaddr
    .sin_family      = AF_INET;//设置地址类型为AF_INET
            servaddr
    .sin_addr.s_addr = htonl(INADDR_ANY);//网络地址为INADDR_ANY
            servaddr
    .sin_port        = htons(SERV_PORT);//端口号
           
           
           
    int opt = 1;
            setsockopt
    (listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));


           
    Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
           
    //将参数listenfd和servaddr绑定在一起,使listenfd这个用于网络通讯的文件描述符监听servaddr所描述的地址和端口号
           
           
    Listen(listenfd, 20);

            maxfd
    = listenfd;       /* 初始化maxfd作为select的第一个参数--最大的文件描述符加一*/
            maxi
    = -1;                      /* index into client[] array */
           
    for (i = 0; i < FD_SETSIZE; i++)
                    client
    [i] = -1; /*初始化client[]为 -1 : 指示可获得的输入项*/
            FD_ZERO
    (&allset);               //清空集合
            FD_SET
    (listenfd, &allset);      //将listenfd文件描述符加入集合之中

           
    for ( ; ; )
           
    {
                    rset
    = allset;  /* structure assignment */
                    nready
    = select(maxfd+1, &rset, NULL, NULL, NULL);//确定rset中套接字的状态
                   
    if (nready < 0)
                            perr_exit
    ("select error");

                   
    if (FD_ISSET(listenfd, &rset)) //判断 listenfd 是否在rset中
                   
    { /* new client connection */
                            cliaddr_len
    = sizeof(cliaddr);
                            connfd
    = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);

                            printf
    ("received from %s at PORT %d ",
                                   inet_ntop
    (AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
                                   ntohs
    (cliaddr.sin_port));

                           
    for (i = 0; i < FD_SETSIZE; i++)
                                   
    if (client[i] < 0)
                                   
    {
                                            client
    [i] = connfd; /* save descriptor */
                                           
    break;
                                   
    }
                           
    if (i == FD_SETSIZE)
                           
    {
                                    fputs
    ("too many clients ", stderr);
                                   
    exit(1);
                           
    }

                            FD_SET
    (connfd, &allset);        /* add new descriptor to set */
                           
    if (connfd > maxfd)
                                    maxfd
    = connfd; /* for select */
                           
    if (i > maxi)
                                    maxi
    = i;       /* max index in client[] array */

                           
    if (--nready == 0)
                                   
    continue;       /* no more readable descriptors */
                   
    }

                   
    for (i = 0; i <= maxi; i++)
                   
    {       /* check all clients for data */
                           
    if ( (sockfd = client[i]) < 0)
                                   
    continue;
                           
    if (FD_ISSET(sockfd, &rset))
                           
    {
                                   
    if ( (n = Read(sockfd, buf, MAXLINE)) == 0)
                                   
    {
                                           
    /* connection closed by client */
                                           
    Close(sockfd);
                                            FD_CLR
    (sockfd, &allset);
                                            client
    [i] = -1;
                                   
    } else
                                   
    {
                                           
    int j;
                                           
    for (j = 0; j < n; j++)
                                                    buf
    [j] = toupper(buf[j]);
                                           
    Write(sockfd, buf, n);
                                   
    }

                                   
    if (--nready == 0)
                                           
    break;  /* no more readable descriptors */
                           
    }
                   
    }
           
    }
    }


    执行过程:
       
    服务器先运行,定义变量并初始化一些变量,for循环,把allset的值赋值给rset,调用select()等待客户端连接,如果有客户端运行,select()返回,判断nready如果小于0就说明出错 退出,否则就判断lisentfd是否在rset里面,在就接受连接,用connfd 代替listenfd 与客户端通信。输出 客户端ip 和端口 ,然后保存 新建的描述符,在判断是否有太多的客户端  若太多 退出。 否则 connfd 保存进allset 然后在把最大的 文件描述符赋值给maxfd.如果此时  --nready 等于0  那么 就再次循环把allset 的值赋值给rset 此时 select()已经有了一个套接字对象处于满足条件的状态。判断 lisentfd是否在rset里面 此时 rsetallset赋值 只有connfd 不再执行if后面的语句。
       
    执行for循环把上一面新建的描述符赋值给sockfd 并判断这个描述符是否小于0 ,如果小于0说明 client[i]里面没有新的文件描述符,就再次回到第一个for循环处执行。否则就判断 sockfd 在不在rset中,如果在,在判断能不能从客户端读取数据,如果能就执行else下面的语句 并把处理过得数据传回客户端,如果不能 说明客户端一关闭连接,就把新建的文件描述符关闭,并从allset中删除,把client[i]赋值为-1。接着判断--nready是否等于0 如果等于0 就退出本次循环,否则在次循环,判断另一个客户端(client[i])是否有输入有输入就处理并返回客户端,没有就关闭另一个客户端描述符。循环结束时,在执行上一个循环 ,重新接受新的客户端请求。一直循环。
                       
     

    <script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
    阅读(527) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~
    评论热议
  • 相关阅读:
    js实现观察者模式
    磁盘阵列操作实战
    淘宝知名工程师
    Java线程并发控制基础知识
    java多线程总结
    NIO系列1:框架拆解
    Java NIO 系列教程
    Java NIO系列教程(三-十二) Buffer
    Java NIO系列教程(二) Channel
    Java NIO系列教程(一) Java NIO 概述
  • 原文地址:https://www.cnblogs.com/ztguang/p/12647515.html
Copyright © 2020-2023  润新知