分类: 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
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
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
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)
这里注意一点: