tag 标签: select()

相关博文
  • 热度 22
    2013-5-18 08:47
    1216 次阅读|
    1 个评论
            自学嵌入式linux时间也不短了,但是作为一个三天打鱼两天晒网的人来说,我学习随意性很强,一般在工作之余看一点儿书、敲几行代码,进度也很慢。现在把总结的一些内容整理成博客,一方面跟大家共同分享一下学习过程,另一方面呢也督促一下自己努力学习!哈哈。下面进入正题,这篇博客的主题是select()函数实现并发服务器。下面直接上代码(带有注释的哦,全是我自己的理解,有误之处恳请各位大牛多多扶持),在代码的最后我用visio做了个简单的流程图,做的很粗糙,希望不会有碍观瞻!          以下代码是select()函数实现并发服务器的程序代码,现对其作出解释: #include #include #include #include #include #include #include #include   #define  BACK_LOG 10 #define BUF_SIZE 1024 #define PORT 8000   int main(int argc, char *argv ;      char buffer ;        fd_set allset,rdset;          struct timeval tv = {0, 0};            if(argc != 2)        {                  printf("Usage: echoserv ");                  exit(1);      }      bzero(servaddr,sizeof(struct sockaddr_in));      servaddr.sin_family = AF_INET;      servaddr.sin_addr.s_addr = INADDR_ANY;        //   servaddr.sin_port = htons(PORT);      servaddr.sin_port = htons(atoi(argv ));             // 端口号由程序运行时作为参数传入         sockfd = socket(AF_INET, SOCK_STREAM, 0);              // 打开通讯端口      if (sockfd == -1)        {                  perror("socket");                  exit(1);      }        ret_val = bind(sockfd, (struct sockaddr *)servaddr, sizeof(struct sockaddr));  //绑定服务器IP和端口      if (ret_val == -1)          {                  perror("bind");                  exit(1);      }           ret_val = listen(sockfd, BACK_LOG);         // 将主动连接套接字变为被动连接套接字      if (ret_val == -1)        {                  perror("listen");                  exit(1);      }       max_fd = sockfd;        FD_ZERO(allset);                                  // 清空描述符集      FD_ZERO(rdset);      FD_SET(sockfd,allset);                           // 将通讯端口描述符加入描述符集中        for(i=0; i FD_SETSIZE; i++)                  client = -1;      max_index = -1;        for(;;)        {                  rdset = allset;                  //nready = select(max_fd+1,rdset,NULL,NULL,NULL);  // 以阻塞方式监听rdset描述符集中是否有可读的描述符                  nready = select(max_fd+1,rdset,NULL,NULL,tv); // 以完全非阻塞方式监听rdset描述符集中是否有可读的描述符             if(FD_ISSET(sockfd, rdset))     // FD_ISSET用来检测描述符集中指定描述符状态是否发生了变化,在此用来检测通讯端口是否有新的请求连接               {                                         clilen = sizeof(cliaddr);                       connfd = accept(sockfd, (struct sockaddr *)cliaddr, clilen);   // 为新建立的连接分配通讯描述符                       if(connfd ==-1)                      {                            perror("accept");                            continue;                       }                       for(i=0; i;                      {                            if(client == -1)                             {                                        client = connfd;  // 填充客户端通讯描述符表                                        break;                            }                       }                               if(i == FD_SETSIZE)          // FD_SETSIZE宏是在哪里定义的?                      {                            printf("Too many client here!");                            exit(1);                       }                       if(i max_index)                            max_index = i;                       if(connfd max_fd)                            max_fd = connfd;                       FD_SET(connfd,allset);                         if(--nready =0)     // 完成对新建的客户端分配描述符之后重新跳select()监控新建立的客户端或者接收已建立客户端的数据发送请求                             continue;                         }             for (i=0; i= max_index; i++)            // 程序运行到此处说明有客户端发送数据请求(select()函数以阻塞方式工作时)以轮询方式服务已建立的客户端               {                       if((clifd=client ) 0)                             continue;                       if(FD_ISSET(clifd,rdset))  // 检查是哪个客户端发起的数据请求,并为服务                      {                            len = BUF_SIZE;                            len = recv(clifd, buffer, len, 0);                            if (len = 0)                             {                                        close(clifd);                                        FD_CLR(clifd,allset);                                        client = -1;                            }                             else                                                     send(clifd,buffer,len,0); // 应用层协议在此实现 ,该范例仅原样返回接收到的字符串                            if(--nready =0)                                          break;                        }//if                        }//for        }//for } 以下是我编写的程序流程图:   附件中是程序源码和visio格式的程序流程图。