linux 应用网络编程 select 多路IO复用

作用:(在一段时间内)检测一个描述符集合的状态。

int select(int nfds,fd_set *readfds,

                fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);

        nfds        目标描述符集合中描述符的数量

        readfds     可读性

        writefds    可写性

        exceptfds   异常情况

        timeout     时长

    select动作仅检查一个描述符集合的状态,执行完毕后会清空整个描述符集合

void FD_CLR(int fd, fd_set *set);   删除集合中的一个描述符

int  FD_ISSET(int fd, fd_set *set); 检查某一个描述符是否存在于集合中

void FD_SET(int fd, fd_set *set);   向集合中添加一个描述符

void FD_ZERO(fd_set *set);          清空一个集合

在linux中所在位置:x86_64-linux-gnu/sys/select.h

示例:

typedef struct{

#ifdef __USE_XOPEN

    __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];

# define __FDS_BITS(set) ((set)->fds_bits)

#else

    __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];

# define __FDS_BITS(set) ((set)->__fds_bits)

#endif

} fd_set;

typedef long int __fd_mask;  长整型

#include <stdio.h>

#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>

#include <sys/select.h>      

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <stdlib.h>

#include <string.h>



/*全局变量*/

fd_set fds;/*描述符集合*/



/*获取描述符集合的最大值*/

static int getNumofFds(fd_set *p_fds){



    int max;

    int i;

    for(i = 0;i < FD_SETSIZE;i++){/*FD_SETSIZE 象征集合能够存放最大的描述符数量0 - 1023*/

        if(FD_ISSET(i,p_fds)){ /*如果检查到该描述符存在于集合中*/

            max = i;

        }

    }

    return max;

}

/*主函数*/

int main(){



   int optval = 1;

   int num_of_fds;

   struct timeval time_value;

   int i;

   fd_set tmp_fds;

   int select_retval;

   char buffer[512] = {0};

   ssize_t recv_ret;



    int listen_skt = socket(PF_INET,SOCK_STREAM,0);/*监听套节字*/

    if(listen_skt < 0){

        perror("socket");

        return -1;

    }



 /*服务端监听套接字*/

    if(setsockopt(listen_skt,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval))){

        perror("setsockopt");

        return -1;

    }



    struct sockaddr_in server_addr;

    server_addr.sin_family      = PF_INET;

    server_addr.sin_port        = htons(60000);

    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    /*绑定本机地址和端口*/

    if(bind(listen_skt,(const struct sockaddr *)&server_addr,sizeof(server_addr))){

        perror("bind");

        return -1;

    }

    /*设置监听端口*/

    if(listen(listen_skt,10)){

        perror("listen");

        return -1;

    }

    system("clear");

    printf("waiting client connect...\n");



    FD_ZERO(&fds);              /*清空集合(初始化)*/

    FD_SET(listen_skt,&fds);    /*将监听套接字放入集合中*/

   

     while(1){

        time_value.tv_sec = 3;

        tmp_fds = fds;  /*拷贝一个集合*/

        num_of_fds = getNumofFds(&tmp_fds) + 1;

        select_retval = select(num_of_fds,&tmp_fds,NULL,NULL,&time_value);

        printf("%d fd in fds.\n",num_of_fds);



        if(select_retval == 0){

            printf("timeout\n");

            perror("select");

        }else if(select_retval > 0){     /*有返回值*/

            if(FD_ISSET(listen_skt,&tmp_fds)){

                int server_skt = accept(listen_skt,NULL,0);   /*接收连接*/

                if(server_skt < 0){

                    perror("accept");

                    return -1;

                }

            FD_SET(server_skt,&fds);

            printf("client %d connected.\n",server_skt);

            usleep(1);



            }else{

                for(i = 0;i < num_of_fds;i++){

                    if(FD_ISSET(i,&tmp_fds)){

                        recv_ret = recv(i,buffer,sizeof(buffer),0);

                    if(recv_ret == 0){

                        break;

                    }

                    if(recv_ret < 0){

                        perror("recv");

                        break;

                    }

                    printf("[recv]:%s\n",buffer);

                    }

                }

            }

        }

     }

    return 0;



}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值