Chinaunix首页 | 论坛 | 博客
  • 博客访问: 559597
  • 博文数量: 142
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1452
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 16:28
文章分类

全部博文(142)

文章存档

2016年(10)

2015年(60)

2014年(72)

我的朋友

分类: C/C++

2014-10-09 10:47:04

#include
#include
int select(int maxfdpl,fd_set *readset,fd_set *writeset,fd_set *exceptset, const struct timeval *timeout)


struct timeval {
long tv_sec;
long tv_usec;
};


1)timeout == NULL,仅在有一个描述符准备好I/0的时候才返回,不然永久等待下去
2)timeout设置为一段时间,在这段时间内,有一个描述符准备好I/0返回,否则超时返回
3)timeout设置为0,检测描述符后立即返回,这称为轮询(polling).
一般情况下timeout是一个常数值,下一次运行时还是保持原来的值,如果要使用剩余时间,必须重新计算。但是linux下,timeout是会更新为剩余时间的。

前面两种情况的等待通过会被进程在等待期间捕获的信号中断,并从信号处理函数返回。


void FD_ZEROS(fd_set *fdset);
void FD_SET(int fd, fd_set *fdset);
void FD_CLR(int fd, fd_set *fdset);
int FD_ISSET(int fd, fd_set *fdset);


如果中间的三个参数readset, writeset, exceptset都为NULL,则select提供了一个微妙级别的定时器。
中间三个参数都是值----结果参数,调用时,指定了我们关心的描述符的值,返回时,结果将指示哪些描述符已就绪。
函数返回后,我们使用FD_ISSET宏来测试fd_set数据类型中的描述符,描述符集内任何与未就绪描述符对应的位都返回为0,所以,每次
重新select时,都需要重新设置关心的位为1.


maxfdpl参数指定了待测试的描述符个数,它的值是待测试的最大描述符总数。 ---------这个参数的作用是提高效率,FD_SETSIZE通常为1024,但实际中通常少于这个值。

返回值表示所有描述符集的已就绪的总位数。如果定时器返回,则返回0。返回-1表示出错。

点击(此处)折叠或打开

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <signal.h>
  5. #include <sys/socket.h>
  6. #include <sys/types.h>
  7. #include <sys/wait.h>
  8. #include <errno.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <sys/wait.h>
  12. #include <strings.h>
  13. #include "readn.h"

  14. int main(int argc,char *argv[])
  15. {
  16.     int ret = 0;
  17.     int listen_fd;
  18.     int conn_fd;
  19.     struct sockaddr_in server_addr;
  20.     struct sockaddr_in client_addr;
  21.     socklen_t len;
  22.     fd_set readset;
  23.     fd_set allset;
  24.     int max_fd;
  25.     int max_i;
  26.     int i;
  27.     int client[FD_SETSIZE];
  28.     char recvline[MAXLINE];
  29.     int n;

  30.     listen_fd = socket(AF_INET,SOCK_STREAM,0);

  31.     if(listen_fd < 0) {
  32.         printf("socket error\n");
  33.         return -1;
  34.     }

  35.     bzero(&server_addr,sizeof(struct sockaddr_in));

  36.     server_addr.sin_family = AF_INET;
  37.     server_addr.sin_port = htons(10000);
  38.     //server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  39.     ret = inet_pton(AF_INET,"127.0.0.1",&server_addr.sin_addr.s_addr);
  40.     if(ret < 0) {
  41.         printf("inet_pton error\n");
  42.         close(listen_fd);
  43.         return ret;
  44.     }else if(ret == 0) {
  45.         printf("the second parameter of inet_addr is null\n");
  46.     }

  47.     if(bind(listen_fd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr)) == -1) {
  48.         printf("bind error\n");
  49.         close(listen_fd);
  50.         return -1;
  51.     }


  52.     if(listen(listen_fd,1024) == -1) {
  53.         printf("listen error\n");
  54.         close(listen_fd);
  55.         return -1;
  56.     }

  57.     FD_ZERO(&allset);
  58.     FD_SET(listen_fd,&allset);
  59.     max_fd = listen_fd;
  60.     for(i = 0;i < FD_SETSIZE;i++)
  61.         client[i] = -1;
  62.     max_i = -1;
  63.     for(;;) {
  64.         readset = allset;
  65.         ret = select(max_fd+1,&readset,NULL,NULL,NULL);
  66.         if(FD_ISSET(listen_fd,&readset)) {
  67.             len = sizeof(client_addr);
  68.             conn_fd = accept(listen_fd,(struct sockaddr*)&client_addr,&len);
  69.             if(conn_fd < 0) {
  70.                 printf("accept error,errno=%d\n",errno);
  71.                 if(errno == EINTR)
  72.                     continue;
  73.                 return -1;
  74.             }
  75.             FD_SET(conn_fd,&allset);
  76.             if(conn_fd > max_fd)
  77.                 max_fd = conn_fd;
  78.             for(i = 0;i < FD_SETSIZE;i++) {
  79.                 if(client[i] == -1) {
  80.                     client[i] = conn_fd;
  81.                     break;
  82.                 }
  83.             }
  84.             if(i == FD_SETSIZE) {
  85.                 printf("error too many fds,exceeds FD_SETSIZE\n");
  86.                 return -1;
  87.             }
  88.             if(i > max_i)
  89.                 max_i = i;
  90.             if(--ret <= 0)
  91.                 continue;
  92.         }
  93.         for(i = 0; i <= max_i;i++)
  94.         {
  95.             if((client[i] != -1) && FD_ISSET(client[i],&readset)) {
  96.                 /*TODO::handle on conn_fd*/
  97.                 if((n=read(client[i],recvline,MAXLINE)) == 0) {
  98.                     close(client[i]);
  99.                     FD_CLR(client[i],&allset);
  100.                     client[i] = -1;
  101.                 }else {
  102.                     writen(client[i],recvline,n);
  103.                 }
  104.                 if(--ret <= 0)
  105.                     break;
  106.             }
  107.         }
  108.     }
  109.     return 0;
  110. }

阅读(879) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~