• socket 中 select 使用指南(转)


    原型

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

    第一个参数 nfds

    在linux下的描述:指定测试的描述符最大值,在0到nfds都会被测试,

    到了windows下: Ignored. The nfds parameter is included only for compatibility with Berkeley sockets. 忽略了。

    从accept开始.

    首先:

    SOCKET sock;
    sock= socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in addr;       //告诉sock 应该再什么地方licence
    memset(&addr,0,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_port=htons(11111);    //端口啦
    addr.sin_addr.s_addr=htonl(INADDR_ANY);             //在本机的所有ip上开始监听
    bind (sock,(sockaddr *)&addr,sizeof(addr));//bind....
    listen(sock,5);                               ;//最大5个队列
    SOCKET socka;                         //这个用来接受一个连接
    fd_set rfd;                                   // 描述符集 这个将用来测试有没有一个可用的连接
    struct timeval timeout;
    FD_ZERO(&rfd);                     //总是这样先清空一个描述符集
    timeout.tv_sec=60;                //等下select用到这个
    timeout.tv_usec=0;
    u_long ul=1;
    ioctlsocket(sock,FIONBIO,&ul);    //用非阻塞的连接
    
    //现在开始用select
    FD_SET(sock,&rfd);    //把sock放入要测试的描述符集 就是说把sock放入了rfd里面 这样下一步调用select对rfd进行测试的时候就会测试sock了(因为我们将sock放入的rdf) 一个描述符集可以包含多个被测试的描述符,
    if(select(sock+1,&rfd,0,0, &timeout)==0)    // select的第一个参数是可以忽略的(这样
    //写是为了保持和linux下一致) 第二个参数放入需要测试的读描述符集(也就是说如果这里面有
    //一个描述符可以读取了,select就返回) 第三个放入需要测试的写描述符集,第四个放入"可执
    //行描述符集"(??我也不知道) 第五个参数是超时时间(如果过了这个超时时间依然没有描述符
    //准备好,select也返回.(如果为NULL,那就一直等到一个描述符集变成准备好的状态)
    { //这个大括号接上面的,返回0那么就超过了timeout预定的时间
    //处理....
    }
    if(FD_ISSET(sock,&rfd))
    {      //有一个描述符准备好了
    socka=accept(sock,0,0);     //好了 接受它吧
    

    //你还要判断一下socka是不是有效的socket才行....

    -------------------------------------------------------------------------------------------------------------------------------

    一般的情况下

    假设你要判断两个socket 是否可读可写 那就这样:

    假设 socka 和sockb 是两个socket 他们已经被连接上,并且能够收发数据

    fd_set rfd,wfd;//一个用来测试读 一个用来测试写
    FD_ZERO(&rfd);
    FD_ZERO(&wfd);
    FD_SET(socka,&rfd);//把socka放入读描述符集
    FD_SET(sockb,&rfd);//把sockb放入读描述符集
    FD_SET(socka,&wfd);把socka放入写描述符集
    FD_SET(sockb,&wfd);把sockb放入写描述符集
    if(SOCKET_ERROR!=select(0,&rfd,&wfd,0,0))      //测试这两个描述符集,永不超时 其中rfd只用来测试读 wfd只用来测试写
    {      //没有错误
    if(FD_ISSET(socka,&rfd))    //socka可读
    {...}
    if(FD_ISSET(sockb,&rfd)   //sockb可读
    {...}
    if(FD_ISSET(socka,&wfd) //socka 可写
    {...}
    if(FD_ISSET(sockb,&wfd) //sockb可写
    {...}
    }
    
    
  • 相关阅读:
    Inner Classes with TypeScript
    设计模式(一)
    C++定义构造函数必须使用初始化列表的场合
    制作Linux下程序安装包——使用脚本打包bin、run等安装包
    Windows下将程序打包为安装包(最为简易的方式)
    在Linux中查看文件的编码及对文件进行编码转换
    libpcap文件格式分析
    static_cast, dynamic_cast, const_cast
    字符1与数字1
    Linux下的多线程编程
  • 原文地址:https://www.cnblogs.com/lebronjames/p/1851290.html
Copyright © 2020-2023  润新知