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