Windows的Select 中,FD_SETSIZE大小默认是64
WinSock2.h
/*
* Select uses arrays of SOCKETs. These macros manipulate such
* arrays. FD_SETSIZE may be defined by the user before including
* this file, but the default here should be >= 64.
*
* CAVEAT IMPLEMENTOR and USER: THESE MACROS AND TYPES MUST BE
* INCLUDED IN WINSOCK2.H EXACTLY AS SHOWN HERE.
*/
#ifndef FD_SETSIZE
#define FD_SETSIZE 64
#endif /* FD_SETSIZE */
根据winSock2.h中的注释,是允许在代码中修改FD_SETSIZE的大小的。
在Microsoft 的 select function (winsock2.h)中说:
The variable FD_SETSIZE determines the maximum number of descriptors in a set. (The default value of FD_SETSIZE is 64, which can be modified by defining FD_SETSIZE to another value before including Winsock2.h.)
所以,如果在代码中,在winSock2.h include 之前,定义了FD_SETSIZE,默认的64就不会生效了。
由于Linux默认的FD_SETSIZE是1024, 所以有需要求的话,
可以在windows编程时,把FD_SETSIZE修改为1024。
输出FD_SETSIZE的大小,和fd_set::fd_array的元素数量。
//#define FD_SETSIZE 1024;
#include
#include
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
return -1;
fd_set* pfds = new fd_set();
std::cout << "FD_SETSIZE " << FD_SETSIZE << std::endl;
std::cout << "fd_array num " << sizeof(pfds->fd_array) / sizeof(SOCKET) << std::endl;
WSACleanup();
}
输出FD_SETSIZE的大小,和fd_set::fd_array的元素数量。
#define FD_SETSIZE 1024
#include
#include
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
return -1;
fd_set* pfds = new fd_set();
std::cout << "FD_SETSIZE " << FD_SETSIZE << std::endl;
std::cout << "fd_array num " << sizeof(pfds->fd_array) / sizeof(SOCKET) << std::endl;
WSACleanup();
}
fd_array是成员位SOCKET的数组,SOCKET是__int64类型,大小8字节。
所以FD_SETSIZE == 1024, fd_array 大小是8KB。
此时我的电脑可用内存为不到6g,我把FD_SETSIZE改为1024 * 1024 * 768,看看会怎么样。
编译报错:
1>D:\Windows Kits\10\Include\10.0.22000.0\um\WinSock2.h(138,17): error C2148: 数组的总大小不得超过 0x7fffffff 字节
即,数组大小不能超过:2147483647。
FD_SETSIZE改为1024 * 1024 * 768时,fd_array大小应该达到了6442450944,所以超过限制了。
把FD_SETSIZE缩小为:2147483647 / 8 = 268,435,455。
此时编译,new报错。
我把FD_SETSIZE再缩小一点:268,435,400。
编译成功,运行成功,程序运行时,通过资源管理器可以看到大概多占用了2g的内存。
所以FD_SETSIZE不能过大,当超出操作系统允许的极限的时候,会导致编译失败,或者运行崩溃。
windows中虽然默认的FD_SETSIZE是61,但可以修改FD_SETSIZE的大小,而且修改方法比较简单。
如果工程中,在多个地方include了winSock2.h,一定要在第一个include之前,声明自定义的FD_SETSIZE,不然自定义还是不会生效。