using select to read from socket and stdin

15,429

Solution 1

Your problem is in the select().
The first parameter is not the number of file descriptors you are passing in read_fds, but it's the highest socket ID + 1.

From the man page:

The first nfds descriptors are checked in each set; i.e., the descriptors from 0 through nfds-1 in the descriptor sets are examined. (Example: If you have set two file descriptors "4" and "17", nfds should not be "2", but rather "17 + 1" or "18".)

So in your code, instead of '2', try passing 's+1'.

Solution 2

You need to specify the highest file descriptor to select:

if (select(s + 1,&read_fds,NULL,NULL,NULL) == -1){

select() needs to know the number of file descriptors that it is supposed to watch.

Share:
15,429

Related videos on Youtube

michauwilliam
Author by

michauwilliam

Updated on May 31, 2022

Comments

  • michauwilliam
    michauwilliam almost 2 years

    I'm writing a ncurses based chat program. At first, I wrote just networking stuff (without ncurses) and everything worked fine, but after adding graphics I can't get the client app to work properly.

    The main problem is reading from stdin and socket at the same time. In ncurses-less version I've used pthread and it worked like charm. Alas, it seems that pthread and ncurses don't go together very well, so I had to find another solution. I thought that select() would do, but it still only reads from stdin and completely ignores the socket.

    Here is the whole code: code

    The interesting part is:

    char message[1024];
    fd_set master;
    fd_set read_fds;
    
    FD_ZERO(&master);
    FD_ZERO(&read_fds);
    
    FD_SET(0,&master);
    FD_SET(s,&master); // s is a socket descriptor
    while(true){
    read_fds = master;
    if (select(2,&read_fds,NULL,NULL,NULL) == -1){
      perror("select:");
      exit(1);
    }
    // if there are any data ready to read from the socket
    if (FD_ISSET(s, &read_fds)){
      n = read(s,buf,max);
      buf[n]=0;
      if(n<0)
      {
        printf("Blad odczytu z gniazdka");
        exit(1);
      } 
      mvwprintw(output_window,1,1,"%s\n",buf);
    }
    // if there is something in stdin
    if (FD_ISSET(0, &read_fds)){
      getstr(message);
      move(CURS_Y++,CURS_X);
      if (CURS_Y == LINES-2){
        CURS_Y = 1;
      }
      n = write(s,message,strlen(message));
      if (n < 0){
        perror("writeThread:");
        exit(1);
      }
    }
    }
    

    It's possible that I don't fully understand how select() works, or maybe I shouldn't have connect()ed the socket.. I'm lost here. I would appreciate any help! Thanks.

    • Mario The Spoon
      Mario The Spoon about 13 years
      also do not use FD_ZERO( 0, use FD_SET( fileno( stdin ), ...
  • michauwilliam
    michauwilliam about 13 years
    it is suppose to watch only 2 descriptors - stdin and s
  • Richard Pennington
    Richard Pennington about 13 years
    No, the number isn't the number of file descriptors, it's the one greater than the highest file descriptor. and "s + 1" is certainly bigger than 2.