大家耳熟能详的方法:
1.修改定义的宏
#undef FD_SETSIZE
#define FD_SETSIZE 1024
2.从boost asio中抽取的代码
class win_fd_set_adapter : noncopyable { public: enum { default_fd_set_size = 1024 }; win_fd_set_adapter() : capacity_(default_fd_set_size), max_descriptor_(invalid_socket) { fd_set_ = static_cast<win_fd_set*>(::operator new( sizeof(win_fd_set) - sizeof(SOCKET) + sizeof(SOCKET) * (capacity_))); fd_set_->fd_count = 0; } ~win_fd_set_adapter() { ::operator delete(fd_set_); } void reset() { fd_set_->fd_count = 0; max_descriptor_ = invalid_socket; } bool set(socket_type descriptor) { for (u_int i = 0; i < fd_set_->fd_count; ++i) if (fd_set_->fd_array[i] == descriptor) return true; if (fd_set_->fd_count == capacity_) { u_int new_capacity = capacity_ + capacity_ / 2; win_fd_set* new_fd_set = static_cast<win_fd_set*>(::operator new( sizeof(win_fd_set) - sizeof(SOCKET) + sizeof(SOCKET) * (new_capacity))); new_fd_set->fd_count = fd_set_->fd_count; for (u_int i = 0; i < fd_set_->fd_count; ++i) new_fd_set->fd_array[i] = fd_set_->fd_array[i]; ::operator delete(fd_set_); fd_set_ = new_fd_set; capacity_ = new_capacity; } fd_set_->fd_array[fd_set_->fd_count++] = descriptor; return true; } bool is_set(socket_type descriptor) const { return !!__WSAFDIsSet(descriptor, const_cast<fd_set*>(reinterpret_cast<const fd_set*>(fd_set_))); } operator fd_set*() { return reinterpret_cast<fd_set*>(fd_set_); } socket_type max_descriptor() const { return max_descriptor_; } private: // This structure is defined to be compatible with the Windows API fd_set // structure, but without being dependent on the value of FD_SETSIZE. We use // the "struct hack" to allow the number of descriptors to be varied at // runtime. struct win_fd_set { u_int fd_count; SOCKET fd_array[1]; }; win_fd_set* fd_set_; u_int capacity_; socket_type max_descriptor_; };
使用该类替代fd_set集合,FD_SET使用该类的方法set来替换,而FD_ISSET则用is_set替代,里面的几个数据类型自己typedef一下,缺少的头文件自己加下,noncopyable是boost里面定义的禁止拷贝类(拷贝构造函数,赋值操作为private类型,构造函数和析构函数定义为protected类型)
class noncopyable { protected: noncopyable() {} ~noncopyable() {} private: // emphasize the following members are private noncopyable( const noncopyable& ); const noncopyable& operator=( const noncopyable& ); };
另外提一下,windows下的FD_SETSIZE指最大可以轮询的个数,而linux的FD_SETSIZE指的是最大文件描述符,如果轮询的描述符大于等于该值,可能就出问题,见man:
Executing FD_CLR() or FD_SET() with a value of fd that is negative or is equal to or larger than FD_SETSIZE will result in undefined behavior.