admin管理员组

文章数量:1613633

首先,在不同的操作系统下,select模型完全兼容么?

fd_set在2种操作系统下的实现方式差别比较大:

linux下面定义,对宏翻译后大概是这样的:

typedef struct
  {
    // 支持1024个文件描述符,而用bit作为掩码使用,每个long是64位,所以除以64
    long int fds_bits[1024 / (8 * 8))];  
  } fd_set;

所以使用掩码方式可以直接按比特位进行设置,和删除;

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

man手册中说明,nfds并不是我们设置了多少个socket,而是最大的fd + 1;

这是因为

1)socket本身就是int从小到大的使用,当设置了最大的,最大值可以保证小的都被覆盖;

2)按照掩码方式使用,设置了大值,之前的都是需要监测的;

windows不同:

#define FD_SETSIZE      64
#endif /* FD_SETSIZE */

typedef struct fd_set {
        u_int fd_count;               /* how many are SET? */
        SOCKET  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
} fd_set;

这里使用了一个很土的数组,加上一个使用的个数;

设置时候是

1)监测是否设置了;

2)如果找不到,则追加;

删除的时候是:

1)找到当前位置;

2)逐个向前挪动;

效率比linux的方式低了很多啊,

所以在使用select时候nfds的设置其实就是实际添加了多少个socket;

总结:为啥微软不采用掩码方式实现?是微软太笨么?

不是,是因为windows下socket的值并不是从小到大的一个递增的小整数,值可能会非常的大,所以不能使用小数组实现掩码。

另外:
`int retval, numevents = 0;
timeval tv;
tv.tv_sec =0;
tv.tv_usec = 0; // windows 设置为0合适

memcpy(&_rfds, &rfds, sizeof(fd_set));
memcpy(&_wfds, &wfds, sizeof(fd_set));
memcpy(&_efds, &efds, sizeof(fd_set));

//int n = efds.fd_count;
	//n =max(_rfds.fd_count, _wfds.fd_count);
//if (n==0)
//	return Utils::getmSecNow();

//printf("select n %d \n", n);
retval = select(maxFd + 1, &_rfds, &_wfds, &_efds, &tv);`

本文标签: 区别系统WindowsLinuxselect