Search code examples
csocketsnetwork-programmingposix-select

select() on STDIN and Incoming Socket


I'm trying to write a very basic chat client in C which communicates with another machine using sockets, and I'm having some issues with understanding select. Here's a quick snippet of the relevant code.

while(1)
  {
    FD_ZERO(&readfds);
    FD_ZERO(&writefds);

    FD_SET(STDIN, &writefds);
    FD_SET(connectFD, &readfds);

    select(connectFD+1, &readfds, &writefds, NULL, NULL);

    if(FD_ISSET(connectFD, &readfds) != 0)
    {
      char buf[1024];
      memset(buf, 0, sizeof(buf));
      int lastBit;

      lastBit = recv(connectFD, buf, sizeof(buf), 0);
      if (lastBit > 0 && lastBit < 1024)
      {
        buf[lastBit] = '\0';
      }
      else
      {
        close(connectFD);
        break;
      }
      printf("%s\n", buf);
    }

    else if (FD_ISSET(STDIN, &writefds))
    {
      char msg[1024];
      memset(msg, 0, sizeof(msg));
      read(STDIN, msg, sizeof(msg));
    }
  }
}

What I'm looking to do is have incoming messages processed as soon as they arrive, and only have outgoing messages sent after I hit ENTER, but what I have now only processes incoming data after I hit ENTER instead of immediately. I assume it's because read is a blocking call and select is returning when there's ANY data in the buffer, not just when there's a newline (which is when read returns), but I don't know how to process this otherwise. Any advice or tips for leading me down the right path?


Solution

  • FD_SET(STDIN, &writefds);
    

    You want to read from STDIN so you should add STDIN to the &readfds and not &writefds. Writing to STDIN is almost always possible so your code effectively got the information that writing is possible to STDIN but then attempts to read from STDIN and hangs there until the read actually gets possible.