When the send()
buffer is full, I set a flag in the write_fds for the given socket and the next iteration tries to send it by checking that write_fds is set.
It works fine setting the flag in write_fds for one socket. But, if I do FD_SET(i, write_fds)
for multiple sockets, only the last socket appears as set and only the last socket gets the data.
If I do write_fds = master;
right before select(2)
, then all of them appear as set and all unsent data is sent to all sockets, but select
always returns.
I'm sure I must be doing something wrong.
FD_ZERO(&master);
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
// socket setting...
// bind...
// listen...
FD_SET(listener, &master);
fdmax = listener; // so far, it's this one
for(;;){
read_fds = master; // copy it
// write_fds = master;
select(fdmax+1, &read_fds, &write_fds, NULL, NULL);
for(i = 0; i <= fdmax; i++){
if(FD_ISSET(i, &read_fds)) {
if(i == listener){
addrlen = sizeof remoteaddr;
newfd = accept(listener, (struct sockaddr * ) & remoteaddr, &addrlen);
FD_SET(newfd, &master);
if(newfd > fdmax)
fdmax = newfd;
fcntl(newfd, F_SETFL, fcntl(newfd, F_GETFL, 0) | O_NONBLOCK);
}else{
// do some reading and then... send
sent = send(i, buf, len, 0);
if ((sent < 0 || (sent == -1 && errno == EWOULDBLOCK))
FD_SET(i, &write_fds);
}
}
else if(FD_ISSET(i, &write_fds) && i != listener){
if((sent = send(i, buf, len - sent, 0)) == len - sent)
FD_CLR(i, &write_fds);
}
}
}
You should have FD_ZERO
and FD_SET
s before calling select function.
E.g.
int res = 0;
for(;;){
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
fdmax = 0;
size_t fd_index;
for (fd_index=0; fd_index<num_of_fd; fd_index++)
{
FD_SET(fd_array[fd_index], &read_fds);
FD_SET(fd_array[fd_index], &write_fds);
if (fdmax < fd_array[fd_index])
fdmax = fd_array[fd_index];
}
// write_fds = master;
res = select(fdmax+1, &read_fds, &write_fds, NULL, NULL);
if( res == 0 )
{
// TIMEOUT ...not your case
}
else if( res < 0 )
{
perror("Select error: ");
}
else
{
// process your data
}
And you cannot write
read_fds = master;
because of fd_set
is a complex struct.
EDIT
As @jeremyP commented sent < 0
should be sent > 0