Increasing limit of FD_SETSIZE and select

Solution 1:

Per the standards, there is no way to increase FD_SETSIZE. Some programs and libraries (libevent comes to mind) try to work around this by allocating additional space for the fd_set object and passing values larger than FD_SETSIZE to the FD_* macros, but this is a very bad idea since robust implementations may perform bounds-checking on the argument and abort if it's out of range.

I have an alternate solution that should always work (even though it's not required to by the standards). Instead of a single fd_set object, allocate an array of them large enough to hold the max fd you'll need, then use FD_SET(fd%FD_SETSIZE, &fds_array[fd/FD_SETSIZE]) etc. to access the set.

Solution 2:

I also suggest using poll if possible. And there exist several "event" processing libraries like libevent or libev (or the event abilities of Glib from GTK, or QtCore, etc) which should help you. There are also things like epoll. And your problem is related to C10k

Solution 3:

It would be better (and easy) to replace with poll. Generally poll() is a simple drop-in replacement for select() and isn't limited by the 1024 of FD_SETSIZE...

fd_set fd_read;
int id = 42;
FD_ZERO(fd_read);
FD_SET(id, &fd_read);
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(id + 1, &fd_read, NULL, NULL, &tv) != 1) {
   // Error.
}

becomes:

struct pollfd pfd_read;
int id = 42;
int timeout = 5000;
pfd_read.fd = id;
pfd_read.events = POLLIN;
if (poll(&pfd_read, 1, timeout) != 1) {
   // Error
}

You need to include poll.h for the pollfd structure.

If you need to write as well as read then set the events flag as POLLIN | POLLOUT.

Solution 4:

In order to use a fd_set larger than FD_SETSIZE, it is possible to define an extended one like this :

#include <sys/select.h>
#include <stdio.h>

#define EXT_FD_SETSIZE 2048
typedef struct
{
    long __fds_bits[EXT_FD_SETSIZE / 8 / sizeof(long)];
} ext_fd_set;

int main()
{
    ext_fd_set fd;
    int s;
    printf("FD_SETSIZE:%d sizeof(fd):%ld\n", EXT_FD_SETSIZE, sizeof(fd));
    FD_ZERO(&fd);
    while ( ((s=dup(0)) != -1) && (s < EXT_FD_SETSIZE) )
    {
        FD_SET(s, &fd);
    }
    printf("select:%d\n", select(EXT_FD_SETSIZE,(fd_set*)&fd, NULL, NULL, NULL));
    return 0;
}

This prints :

FD_SETSIZE:2048 sizeof(fd):256

select:2045


In order to open more than 1024 filedescriptors, it is needed to increase the limit using for instance ulimit -n 2048.

Solution 5:

actually there IS a way to increase FD_SETSIZE on windows. its defined in winsock.h and per microsoft themselves you can increase it by simply defining it BEFORE you include winsock.h

http://support.microsoft.com/kb/111855

I do it all the time and have had no problems largest value I have used was around 5000 for a server I was developing