Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1064087
  • 博文数量: 284
  • 博客积分: 8223
  • 博客等级: 中将
  • 技术积分: 3188
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-01 13:26
文章分类

全部博文(284)

文章存档

2012年(18)

2011年(33)

2010年(83)

2009年(147)

2008年(3)

分类: C/C++

2009-07-17 17:15:46

      好多文档上都在说,select 比阻塞好啊。。。我倒觉着,不尽然。反正东西总是因为有用处才会出现,这里写下我对select 的看法。

      select用在一个进程同时监听几个socket端口的情况。在这种情况下,程序可以阻塞在select,当出现可以操作的情况时,再对相应的端口进行读取或写入操作。因为在阻塞的情况下,程序不占用CPU,所以,说select比非阻塞好,而因为同时能够处理多个socket,所以说比阻塞方式IO好。

      这里个人感觉,也有可能是自个的应用没有这个需求,如果我需要多个socket进行操作,我完全可以fork进程出来,让每个进程操作一个端口并阻塞在该端口的通讯上。由于各个端口互不影响,多进程自个阻塞,也不占用CPU,编程还相对多路复用方便,不是更实用吗?? 猜想,是不是多路复用适合于连接数太多,没有办法每个连接都进行fork的情况? 先想到这里,后面附上自个调试的代码,分两个程序,一个host,一个client,两个程序建立5个连接,测试多路复用同时监听5个连接的能力。

host.c:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define NUM 5
void main(int argc, char **argv[])
{
   int fd, fd1;
   int len, i;
   struct sockaddr_in add;
   struct fd_set fds;
   struct timeval timeout;
   char msg[100];
   int Cfd[NUM];
   int count = 0;
   int code;
   timeout.tv_sec = 2;
   timeout.tv_usec = 0;

   len = sizeof(add);
   bzero(&add, len);
   add.sin_family=AF_INET;
   add.sin_port=htons(10000);
   add.sin_addr.s_addr=htonl(INADDR_ANY);
   fd = socket(AF_INET, SOCK_STREAM, 0);
   if(fd < 0) printf("socket err\n");
   bind(fd, (struct sockaddr *)&add, len);
   listen(fd, SOCK_STREAM);
   while(1){
      fd1 = accept(fd, (struct sockaddr *)&add, &len);
      if(fd1>0) {
         Cfd[count++]=fd1;
         printf("accept %d \n", count);
         if(count == NUM) break;
      }
      sleep(1);
   }
   printf("end accept\n");
   while(1){
      printf("now circlie\n");
     FD_ZERO(&fds);
     fd1 = 0;
     for(i=0;i        FD_SET(Cfd[i],&fds);
        if(fd1< Cfd[i])fd1 = Cfd[i];
     }
     fd1 = fd1+1;
     code = select(fd1, &fds, NULL, NULL, &timeout);
     printf("select:%d\n", code);
     if(code > 0){
        for(i=0;i           if(FD_ISSET(Cfd[i], &fds)){
              memset(msg, 0,sizeof(msg));
              recv(Cfd[i], msg, 100, 0);
              printf("%d:recv %s\n",i,msg);
           }
        }
     }
     sleep(1);
   }
   close(fd);
   for(i=0;i}
cli.c:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define NUM 5

void main(int argc, char **argv[])
{
   int fd[NUM];
   int len, i;
   struct sockaddr_in add;
   char msg[100];

   len = sizeof(add);
   bzero(&add, len);
   add.sin_family=AF_INET;
   add.sin_port=htons(10000);
   add.sin_addr.s_addr=inet_addr("10.144.15.234");
   for(i=0;i     fd[i] = socket(AF_INET, SOCK_STREAM, 0);
     if(fd[i]<0) printf("fd%d socket err\n", i);
     connect(fd[i], (struct sockaddr *)&add, len);
     printf("connect: %d\n", i);
   }
   printf("connect end\n");
   sleep(10);
   //上面的延时用于验证select的主机延时阻塞功能
   for(i=4;i>-1;i--){
      sprintf(msg, "i am %d\n", i);
      send(fd[i], msg, strlen(msg), 0);
      printf("send :%s\n", msg);
      sleep(5);
   }
   for(i=0;i}
makefile:

LIB = -lsocket -lnsl
all : clean  host  cli
.PHONY : all
clean :
 -rm *.o sem core
cli : cli.o
 cc -o cli cli.o $(LIB)
cli.o : cli.c
 cc -c cli.c $(LIB)
host : host.o
 cc -o host host.o $(LIB)
host.o : host.c
 cc -c host.c $(LIB)
  

   这里注意一点:

   如果希望程序在接受数据时延时阻塞一定按照下面的写法做:
      select(fd1, &fds, NULL, NULL, &timeout);
   因为select的第2~4个参数分表表示接受阻塞、发送阻塞、错误阻塞,这里只有提供第二个参数才能达到相应的效果。
阅读(3446) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

wangshu8182015-04-29 08:42:21

文明上网,理性发言...