select示例

#include <sys/select.h>  

#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>

int select(int nfds,  fd_set * readfds,  fd_set * writefds,  fd_set * exceptfds,  const struct timeval * timeout);

 

ndfsselect监视的文件句柄数,视进程中打开的文件数而定,一般设为要监视各文件中的最大文件描述符值加1。

 

readfds这个文件描述符集合监视文件集中的任何文件是否有数据可读,当select函数返回的时候,readfds将清除其中不可读的文件描述符,只留下可读的文件描述符。

 

writefds这个文件描述符集合监视文件集中的任何文件是否有数据可写,当select函数返回的时候,writefds将清除其中不可写的文件描述符,只留下可写的文件描述符。

 

exceptfds这个文件集将监视文件集中的任何文件是否发生错误,其实,它可用于其他的用途,例如,监视带外数据OOB,带外数据使用MSG_OOB标志发送到套接字上。当select函数返回的时候,exceptfds将清除其中的其他文件描述符,只留下标记有OOB数据的文件描述符。

 

timeout本次select()的超时结束时间。这个参数至关重要,它可以使select处于三种状态:

 

(1)若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;

 

(2)若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;

 

(3)timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。

 

函数的返回值

 

正值:表示监视的文件集中有文件描述符符合要求

 

零值:表示select监视超时

 

负值:表示发生了错误,错误值由errno指定。

 

宏操作

 

FD_ZERO(fd_set *set):          用来清除描述词组set的全部位
FD_SET(int fd,fd_set*set):     用来设置描述词组set中相关fd的位
FD_ISSET(int fd,fd_set *set): 用来测试描述词组set中相关fd 的位是否为真
FD_CLR(inr fd,fd_set* set):    用来清除描述词组set中相关fd 的位

 

注意事项

 

(1)对于可写性的检查,最好放在需要写数据的时候进行检查。如果和可读性放在同一个地方进行检查,那么select很可能每次都会因为可写性检查成功而返回。 

 

(2)select()调用会清空传递给它的集合参数中的内容,也就是会清空readfds、writefd、exceptfds这三个指针参数所指定的描述符集合。因此,在每次调用select()之前,必须重新初始化并把需要监视的描述符填写到相应的描述符集合中。select()调用也会清空timeout指针所指向的struct timeval结构,所以在每次调用select()之前也要重新填充timeout指针所指向的struct timeval结构。

 

 

 

 

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_FD 1024

volatile int max = -1;

int listenfd ;
char buf[1024];
fd_set read_fds;
fd_set exception_fds;

int sel_fd_arr[MAX_FD];

int get_max_fd(){
int i;
for (i = MAX_FD-1; i >= 0; i--)
if (sel_fd_arr[i] == 0)
return i;

return -1;
}

void set_sel_events(){
int i;
for (i = 0; i < MAX_FD; i++)
if (sel_fd_arr[i] == 0){
FD_SET(i, &read_fds);
FD_SET(i, &exception_fds);
}
}

 

void * sel_thread_fun(void * arg){

struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
char addr_p[16];

int i = 0;
printf("sel_thread_fun begin\n");
while(1){
max = get_max_fd();
printf("max=%d\n", max);

int ret = select(max+1, &read_fds, NULL, &exception_fds, NULL);
if (ret < 0){
printf("selection failure \n");
continue;
}


for (i = 0; i < max+1; i++){
memset(buf, 0x00, sizeof(buf) );
if (FD_ISSET(i, &read_fds)){
if (i == listenfd){
int connfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addrlength);
printf("connection from %s \n", inet_ntop(AF_INET, &client_address.sin_addr, addr_p, sizeof(addr_p)));
if ( connfd < 0){
printf("errno is %d\n", errno);
close(listenfd);
}

sel_fd_arr[connfd] = 0;
}
else{
ret = recv(i, buf, sizeof(buf)-1, 0);
if (ret <= 0){
printf("recv ret=%d\n", ret);
sel_fd_arr[i] = -1;
break;
}
printf("get %d bytes of normal data:%s\n", ret, buf);
}
}
else if( FD_ISSET(i, &exception_fds) ){
ret = recv(i, buf, sizeof(buf)-1, MSG_OOB);
if (ret <= 0){
sel_fd_arr[i] = -1;
break;
}
printf("get %d bytes of oob data:%s\n", ret, buf);
}
}

set_sel_events();

}

return (int*)(1) ;
}

int main(int argc, char *argv[]){

if (argc <= 2){
printf("usage:%s ip_address port_number \n", argv[0]);
return 1;
}

int i;
for (i = 0; i < MAX_FD; i++)
sel_fd_arr[i] = -1;

char addr_p[16];

const char *ip = argv[1];
int port = atoi(argv[2]);

int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);

address.sin_port = htons(port);
listenfd = socket(PF_INET, SOCK_STREAM, 0);
assert(listenfd >= 0);

ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address) );
assert(ret != -1);
ret = listen(listenfd, 5);
assert(ret != -1);

FD_ZERO(&read_fds);
FD_ZERO(&exception_fds);

struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);

sel_fd_arr[listenfd] = 0;
FD_SET(listenfd, &read_fds);
FD_SET(listenfd, &exception_fds);

pthread_t thd;

pthread_create(&thd, NULL, sel_thread_fun, NULL);

pthread_join(thd, NULL);


/*
while(1){
int connfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addrlength);
printf("connection from %s \n", inet_ntop(AF_INET, &client_address.sin_addr, addr_p, sizeof(addr_p)));
if ( connfd < 0){
printf("errno is %d\n", errno);
close(listenfd);
}
if ( connfd > max)
max = connfd;

FD_SET(connfd, &read_fds);
FD_SET(connfd, &exception_fds);
}

*/

close(listenfd);


return 0;

 


}

posted @ 2016-06-06 09:31  Andy.gbhu  阅读(652)  评论(0编辑  收藏  举报