Reputation: 455
I must be doing something wrong at setting up select()
and write_fds
. Currently, when I call sendData()
, for the first time, it sends 117 bytes (all of it) from the buffer. Then immediately it's called again even there's no more data to send in the buffer and it keeps calling sendData()
forever.
Any idea what I am doing wrong here?
int readData(int j){
return recv(j, buf , nbytes , 0);
}
int sendData(int j){
unsigned v = fcntl(j, F_GETFL, 0);
fcntl(j, F_SETFL, v | O_NONBLOCK);
return send(j, buf, nbytes, 0);
}
fd_set master;
fd_set read_fds;
fd_set write_fds;
int fdmax;
...
FD_ZERO(&master);
FD_SET(socket, &master);
fdmax = socket;
for(;;){
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
read_fds = master;
write_fds = master;
if(select(fdmax+1, &read_fds, &write_fds, NULL, NULL) == -1){
exit(4);
}
for(i = 0; i <= fdmax; i++){
if(FD_ISSET(i, &read_fds)){
if(i == socket){
// handle new connections
addrlen = sizeof remoteaddr;
newfd = accept(socket, (struct sockaddr *)&addr, &addrlen);
FD_SET(newfd, &master);
if(newfd > fdmax) fdmax = newfd;
}else{
// we got some data from a client
readData(i);
}
} else if(FD_ISSET(i, &write_fds)){
if(i != socket){
// send data when notified
sendData(i);
}
}
}
}
Upvotes: 1
Views: 2340
Reputation: 310907
Sockets are almost always writeable. You should only select on a socket for writeability if you have previously had an EAGAIN/EWOULDBLOCK from a send()
, and you should cease doing so when the write has been retried and succeeded.
Upvotes: 0
Reputation: 126213
You're asking select to notify you when there is space in the network stack to send more data (that's what the write_fds are checking). Since you've only written 117 bytes, there's plenty of space, so it returns immediately, telling you to write more data.
As you don't have more data to send, what you want to do is remove that file descriptor from the write_fds
set. You only want to add it to write_fds
if the call to send
returned a short write (unable to write all the data), or EWOULDBLOCK (assuming you have it set to non-blocking mode).
That brings up the major problem with your code -- you're calling send/recv without checking the return value, so you have no idea how much data was actually sent or received.
Upvotes: 2