Question

I have a client and server, and the client runs a select loop to multiplex between a TCP and a UDP connection. I'm trying to add my TCP connection file descriptor to both the read and the write set and then initiate one message exchange using write set and one using read set. My message communication with the write set works fine but with the read set I'm unable to do so.

Client Code:

    char buf[256] = {};
    char buf_to_send[256] = {};
    int nfds, sd, r;
    fd_set rd, wr;
    int connect_init = 1;

/* I do the Connect Command here */

    FD_ZERO(&rd);
    FD_ZERO(&wr);

    FD_SET(sd, &rd);
    FD_SET(sd, &wr);

    nfds = sd;


    for(; ;){

       r = select(nfds + 1, &rd, &wr, NULL, NULL);

       if(connect_init == 0){

          if(FD_ISSET(sd, &rd)){    // this is not working, if I change rd to wr, it works!

          r = recv(sd, buf, sizeof(buf),0);
          printf("received buf  = %s", buf);
          sprintf(buf, "%s", "client_reply\n");
          send(sd, buf, strlen(buf), 0);

      }
   }
/* Everything below this works correctly */
if (connect_init){

   if(FD_ISSET(sd, &wr)){

     sprintf(buf_to_send, "%s", "Client connect request");
     write(sd, buf_to_send, strlen(buf_to_send)); 

     recv(sd, buf, sizeof(buf), 0);
     printf("Server said = %s", buf);  

     sprintf(buf_to_send, "Hello!\n"); // client Hellos back
     send(sd, buf_to_send, strlen(buf_to_send), 0);

   }
   connect_init = 0;
  }

} // for loops ends
Was it helpful?

Solution

You need to initialize the sets in the loop, every time before calling select. This is needed because select modifies them. Beej's Guide to Network Programming has a comprehensive example on one way to use select.

So in your code, it seems select returns first with writing allowed, but reading not, which has the read bit reset to 0, and then there's nothing to set it back to 1, because from then on select will not touch it, because it is already 0.

If select API bothers you, look at poll, it avoids this (note that there's probably no practical/efficiency difference, it basically boils down to personal preference). On a "real" code with many descriptors (such as a network server with many clients), where performance matters, you should use some other mechanism though, probably some higher level event library, which then uses the OS specific system API, such as Linux's epoll facility. But checking just a few descriptors, select is the tried and true and relatively portable choice.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top