I'm new to socket programming and I've been introduced to the select()
system call. My question is, lets say I'm writing a server in C (which I am attempting to do) and I want to use the select()
call in my implementation for practice. I'm trying to write a server that receives information from a client, so my approach is to use select()
, followed by read()
and just output the information.
According to the documentation I've read select()
returns the number of file descriptors in the input set which are ready for i/o. My question is, how do know which file descriptors in the original set are the ones that are ready for i/o? I can't seem to find this in my searches or examples I've looked at for the past while.
Let's say my code looks like the below:
int main() {
/* Create socket/server variables */
int select_value;
int this_socket;
int maxfd;
struct sockadder_in address;
fd_set allset;
/* Bind the socket to a port */
main_socket = socket(AF_INET, SOCK_STREAM, 0);
if (main_socket < 0) {
perror("socket()");
exit(1);
}
Connect(main_socket, (struct sockaddr *)&address, sizeof(address));
/* Add the socket to the list of fds to be monitored */
FD_ZERO(&allset);
FD_SET(main_socket, &allset);
fd_set read_ready = allset;
fd_set write_ready = allset;
while (1) {
/* Listen for a connection */
/* Accept a connection */
select_value = Select(maxfd+1, &read_ready, &write_ready, NULL, NULL);
if (select_value == -1) {
perror("select()");
exit(1);
}
else if(select_value > 0) {
/* How to access i/o ready file descriptors
now that we know there are some available? */
}
}
}
One can do this using the FD_ISSET
macro that is part of <sys/select.h>
.
When your select
unblocks and a file descriptor is ready, you can test all of your file descriptors using the FD_ISSET
macro in a simple loop. This can be translated to the following sample :
for (i = 0; i < FD_SETSIZE; ++i) {
if (FD_ISSET (i, &read_fd_set)) {
if (i == bound_socket) {
// A new client is waiting to be accepted
new = accept(sock, (struct sockaddr *) &clientname, &size);
// ...
FD_SET (new, &active_fd_set);
}
else {
// There is something to be read on the file descriptor.
data = read_from_client_on(i);
}
}
}
Of course, this is just sample which is obviously lacking any error handling, which you should handle in your application.