[IO复用] Windows Select FD_SETSIZE 大小修改

文章目录

  • 简介
  • 试验代码
    • 没有自定义FD_SETSIZE宏
    • 自定义FD_SETSIZE
    • 自定义FD_SETSIZE最大能多大
  • 结果

简介

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_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();
}

[IO复用] Windows Select FD_SETSIZE 大小修改_第1张图片
是默认值64;

自定义FD_SETSIZE

输出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();
}

[IO复用] Windows Select FD_SETSIZE 大小修改_第2张图片
被修改成了1024

自定义FD_SETSIZE最大能多大

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,不然自定义还是不会生效。

你可能感兴趣的:(网络编程,windows,linux,网络协议,c++)