Welcome

首页 / 软件开发 / C++ / 突破select的FD_SETSIZE限制

突破select的FD_SETSIZE限制2011-04-04Kevin Lynx前言:

在很多比较各种网络模型的文章中,但凡提到select模型时,都会说 select受限于轮询的套接字数量,这个数量也就是系统头文件中定义的FD_SETSIZE值(例 如64)。但事实上这个算不上真的限制。

C语言的偏方:

在C语言的世界里 存在一个关于结构体的偏门技巧,例如:

typedef struct _str_type
{
int _len;
char _s[1];
} str_type;

str_type用于保存字符串(我只是举例,事实上这个结构体没什 么用处),乍看上去str_type只能保存长度为1的字符串("")。但是,通过写下如 下的代码,你将突破这个限制:

int str_len = 5;
str_type *s = (str_type*) malloc( sizeof( str_type ) + str_len - 1 );
//
free( s );

这个技巧原理很简单,因为_s恰好在结构体尾部,所以可以为其分配一 段连续的空间,只要注意指针的使用,这个就算不上代码上的罪恶。但是这个技巧有个限 制,str_type定义的变量必须是被分配在堆上,否则会破坏堆栈。另外,需要动态增长的 成员需要位于结构体的末尾。最后,一个忠告就是,这个是C语言里的技巧,如果你的结 构体包含了C++的东西,这个技巧将不再安全(<Inside the C++ object model>)。

其实select也可以这样做:

事实上,因为select涉及到的fd_set是一个完 全满足上述要求的结构体:

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

但是,如果使用了以上技巧来增加fd_array的数量(也就是保存的 套接字数量),那么关于fd_set的那些宏可能就无法使用了,例如FD_SET。

winsock2.h :

#define FD_SET(fd, set) do { 
u_int __i;
for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) {
if (((fd_set FAR *)(set))->fd_array[__i] == (fd)) {
break;
}
}
if (__i == ((fd_set FAR *)(set))->fd_count) {
if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) {
((fd_set FAR *)(set))->fd_array[__i] = (fd);
((fd_set FAR *)(set))->fd_count++;
}
}
} while(0)