• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Unix网络编程FD_SET

武飞扬头像
工丨具丨人
帮助3

fd_set结构体

fd_set的定义

 typedef struct
  {
    __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
    # define __FDS_BITS(set) ((set)->__fds_bits)
  } fd_set;

可简化为

typedef struct{
       long int __fds_bits[1024/(8*sizeof(int long))];
   };

即其中只有一个字段为__fds_bits,它的类型是long int的数组,数组元素个数为1024/(8本机long的字节数),
而(8
本机long的字节数)是本机long占用的bit数,这样就保证了
__fds_bits的字节数必为1024(select可以监听的最大描述符数),而且用long存储

FD_SET宏

FD_SET宏

 #define __FD_SET(d, set) \
  ((void) (__FDS_BITS (set)[__FD_ELT (d)] |= __FD_MASK (d)))

其展开为

((void)((set)->__fds_bits)[((d)/8 * (int) sizeof (long int))] |= ((long int) (1UL << ((d) % (8 * (int) sizeof (long int))))))

其中的宏都可以在sys/select.h中找到
这个宏操作如下:

  1. 获取到传入fd_set指针的__fds_bits的第(d/当前主机long的字节数)个元素,也就是第d个bit所在的那个long元素
  2. 计算出将1UL(即longint的1)左移(d%当前主机long的字节数)
  3. 最后将第一步的数字与第二步的数字进行或操作,得到结果

比如在64位机器上FG_SET(rset, 73)
假设原来rset的第二个long元素是
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

  1. 73/64 = 第二个元素
  2. 73/64 = 1UL左移9位,得到
    00000000 00000000 00000000 00000000 00000000 00000000 00000010 00000000
  3. 进行或操作,得到
    00000000 00000000 00000000 00000000 00000000 00000000 00000010 00000000
    这样就可以把第73位置的bit置为1(注意不是从低内存到高内存直接数的73)

对结果进行打印

运行程序

#include "stdio.h"
#include "sys/select.h"
int main(){
    fd_set rset;
    FD_ZERO(&rset);
    // 打印下此时的rset
    int fortimes = 1024/(int)(8*sizeof(long int));
    printf("now FD_ZERO the fd_set:\n");
    for (int i=0;i<fortimes;i  ){
        printf("rset [%d] %lu\n", i, rset.__fds_bits[i]);
    }
    // 使用FD_SET
    FD_SET(0, &rset);
    FD_SET(73, &rset);
    FD_SET(1023, &rset);
    // 打印下此时的rset
    printf("now r_set after fd_set:\n");
    for (int i=0;i<fortimes;i  ){
        printf("rset [%d] %lu\n", i, rset.__fds_bits[i]);
    }
}
学新通

得到结果
学新通

结果分析

1.在内存中,一个字节中bit的保存是按我们可读的方式进行保存的
如 1UL在小端机器保存为
00000001 00000000 00000000 00000000
我们可以通过这个程序证实

#include <stdio.h>
union ic{
    int a;
    char b[4];
};
int main(){
    union ic ic_obj;
    ic_obj.a = 1;
    for (int i=0;i<4;i  ){
        printf("%d\n", ic_obj.b[i]);
    }
    // 对int左移
    ic_obj.b[0]<<=1;
    for (int i=0;i<4;i  ){
        printf("%d\n", ic_obj.b[i]);
    }
}
学新通

学新通
2.对于与操作,无论大端序还是小端序,最后或出来的结果是一样的,因为一个机器的字节读取顺序是不变的.
比如int类型的1或上int类型的2
对于大端序机器
00000000 00000000 00000000 00000001 或
00000000 00000000 00000000 00000010 得
00000000 00000000 00000000 00000011 机器转为int是3
对于小端序机器
00000001 00000000 00000000 00000000 或
00000010 00000000 00000000 00000000 得
00000011 00000000 00000000 00000000 机器转int也是3

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhhhfjkg
系列文章
更多 icon
同类精品
更多 icon
继续加载