• 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 ");
    while(1){
    max = get_max_fd();
    printf("max=%d ", max);

    int ret = select(max+1, &read_fds, NULL, &exception_fds, NULL);
    if (ret < 0){
    printf("selection failure ");
    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 ", inet_ntop(AF_INET, &client_address.sin_addr, addr_p, sizeof(addr_p)));
    if ( connfd < 0){
    printf("errno is %d ", errno);
    close(listenfd);
    }

    sel_fd_arr[connfd] = 0;
    }
    else{
    ret = recv(i, buf, sizeof(buf)-1, 0);
    if (ret <= 0){
    printf("recv ret=%d ", ret);
    sel_fd_arr[i] = -1;
    break;
    }
    printf("get %d bytes of normal data:%s ", 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 ", ret, buf);
    }
    }

    set_sel_events();

    }

    return (int*)(1) ;
    }

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

    if (argc <= 2){
    printf("usage:%s ip_address port_number ", 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 ", inet_ntop(AF_INET, &client_address.sin_addr, addr_p, sizeof(addr_p)));
    if ( connfd < 0){
    printf("errno is %d ", errno);
    close(listenfd);
    }
    if ( connfd > max)
    max = connfd;

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

    */

    close(listenfd);


    return 0;


    }

  • 相关阅读:
    Spring 核心API
    python装饰器
    python作业(day1)
    Kali Linux 更新源
    一维数组模拟数据结构-------栈
    Spring事务管理
    Linux用户管理命令
    Linux 帮助命令
    Spring对jdbc的支持
    springboot集成shiro 循环重定向
  • 原文地址:https://www.cnblogs.com/hugb/p/5562770.html
Copyright © 2020-2023  润新知