我正在读wrox系例中的Beginning Linux Programming,其中socket编程中,针对select用法所举的例子百思不得其解,特请大家帮忙分析指正。
例子是关于一个服务器程序实现对多个客户同时处理的
server1.c 用fork()实现
server2.c 用select()实现
server1.c 主要代码如下:
while(1) {
char ch;
printf("server waiting\n");
/* Accept connection. */
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
/* Fork to create a process for this client and perform a test to see
whether we're the parent or the child. */
if(fork() == 0) {
/* If we're the child, we can now read/write to the client on client_sockfd.
The five second delay is just for this demonstration. */
read(client_sockfd, &ch, 1);
sleep(5);
ch++;
write(client_sockfd, &ch, 1);
close(client_sockfd);
exit(0);
}
/* Otherwise, we must be the parent and our work for this client is finished. */
else {
close(client_sockfd);
}
}
server2.c 主要代码如下:
FD_ZERO(&readfds);
FD_SET(server_sockfd, &readfds);
/* Now wait for clients and requests.
Since we have passed a null pointer as the timeout parameter, no timeout will occur.
The program will exit and report an error if select returns a value of less than 1. */
while(1) {
char ch;
int fd;
int nread;
testfds = readfds;
printf("server waiting\n");
result = select(FD_SETSIZE, &testfds, (fd_set *)0,
(fd_set *)0, (struct timeval *) 0);
if(result < 1) {
perror("server5");
exit(1);
}
/* Once we know we've got activity,
we find which descriptor it's on by checking each in turn using FD_ISSET. */
for(fd = 0; fd < FD_SETSIZE; fd++) {
if(FD_ISSET(fd,&testfds)) {
/* If the activity is on server_sockfd, it must be a request for a new connection
and we add the associated client_sockfd to the descriptor set. */
if(fd == server_sockfd) {
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
FD_SET(client_sockfd, &readfds);
printf("adding client on fd %d\n", client_sockfd);
}
/* If it isn't the server, it must be client activity.
If close is received, the client has gone away and we remove it from the descriptor set.
Otherwise, we 'serve' the client as in the previous examples. */
else {
ioctl(fd, FIONREAD, &nread);
if(nread == 0) {
close(fd);
FD_CLR(fd, &readfds);
printf("removing client on fd %d\n", fd);
}
else {
read(fd, &ch, 1);
sleep(5);
printf("serving client on fd %d\n", fd);
ch++;
write(fd, &ch, 1);
}
}
}
}
}
文章的意思是,server2.c 既能借助select()实现server1.c 的及时处理多客户的请求,又避免了server1.c 中有fork()的资源浪费,
问题是:
我看不出server2.c 中的代码实现有任何能 及时处理 多客户请求的地方。
和以下最简单的代码效率是相同的
listen(server_sockfd, 5);
while(1) {
char ch;
printf("server waiting\n");
/* Accept a connection. */
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
/* We can now read/write to client on client_sockfd. */
read(client_sockfd, &ch, 1);
ch++;
write(client_sockfd, &ch, 1);
close(client_sockfd);
}
大家分析一下,select()的作用到底在哪里?
还有select()一般都用在何处场合?