doesn't. It works the first time around, but the next time it runs through the while loop it gets a timeout even if the sd socket receives data. It seems to me to be a waste of resources to have to empty and fill set every time.

Anybody have a good explanation why this is, and even better, perhaps a suggestion how to avoid it?

3 Answers
3

select modifies its arguments. You really do have to re-initialize it each time.

If you're concerned about overhead, the cost of processing the complete FD_SET in the kernel is somewhat more significant than the cost of FD_ZERO. You'd want to only pass in your maximum fd, not FD_SETSZIZE, to minimize the kernel processing. In your example:

switch (select((sd + 1),&set,NULL,NULL,&timeout))

For a more complex case with multiple fds, you typically end up maintaining a max variable:

If you will have a large number of file descriptors and are concerned about the overhead of schlepping them about, you should look at some of the alternatives to select(). You don't mention the OS you're using, but for Unix-like OSes there are a few:

for Linux, epoll()

for FreeBSD/NetBSD/OpenBSD/MacOS X, kqueue()

for Solaris, /dev/poll

The APIs are different, but they are all essentially a stateful kernel interface to maintain a set of active file descriptions. Once an fd is added to the set, you will be notified of events on that fd without having to continually pass it in again.

For an alternative to select(), why not poll() which, unlike the ones you mention, is the same on many Unices?
–
bortzmeyerNov 13 '08 at 12:47

1

poll() is better in that you don't have to reinitialize its array each time, but you're still copying a large structure in and out of the kernel on every call. If you have a lot of fds, the other alternatives avoid this constant overhead by modifying the fd set in the kernel.
–
DGentryNov 13 '08 at 14:03

That's the way select works. It works best, and makes more sense, if you have more than one socket. That's kind of the point: you are selecting across many sockets. If you want to read from one socket, just read or recv it.

Read doesn't offer timeout. Hence the use of select. + the fact that I will be adding a second socket later in the development stage.
–
deadcycloNov 12 '08 at 23:54

Just to keep offering alternatives: if sd is a socket you can use setsockopt(sd, SO_RCVTIMEO, ...) to add a read timeout. However if you are going to add a second socket later, select is the better option to pursue.
–
DGentryNov 13 '08 at 19:58

I know about the FD_ISSET, but I haven't included it yet, because as of now I'm only listining to one socket (I'll be adding more sockets later on). So there is now way to be able to "reuse" without having to set fd_set first?
–
deadcycloNov 12 '08 at 23:53

The documented behavior of select() includes modifying the sets in place. To quote The Pragmatic Programmer, "'select' isn't broken".
–
bk1eNov 13 '08 at 3:44