используя выбор для чтения из сокета и стандартного ввода - PullRequest
4 голосов
/ 29 апреля 2011

Я пишу чат-программу на основе ncurses.Сначала я писал только сетевые материалы (без ncurses), и все работало нормально, но после добавления графики я не могу заставить клиентское приложение работать должным образом.

Основная проблема - чтение из stdin и socket вв то же время.В версии без ncurses я использовал pthread, и он работал как шарм.Увы, кажется, что pthread и ncurses не очень хорошо сочетаются друг с другом, поэтому мне пришлось искать другое решение.Я думал, что будет делать select (), но он все еще только читает из stdin и полностью игнорирует сокет.

Вот весь код: code

Интересная часть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);
  }
}
}

Возможно, я не до конца понимаю, как работает select (), или, возможно, мне не нужно было подключать connect () к сокету ... Я здесь потерян.Буду признателен за любую помощь!Спасибо.

Ответы [ 2 ]

6 голосов
/ 29 апреля 2011

Ваша проблема в select().
Первый параметр не количество файловых дескрипторов, которые вы передаете read_fds , но это самый высокий идентификатор сокета +1.

со страницы руководства:

Первые дескрипторы nfds проверяются в каждом наборе;то есть дескрипторы от 0 до nfds-1 в наборах дескрипторов.(Пример: если вы установили два файловых дескриптора «4» и «17», nfds должен быть не «2», а «17 + 1» или «18».)

ваш код вместо '2', попробуйте передать 's + 1'.

1 голос
/ 29 апреля 2011

Вам нужно указать самый высокий дескриптор файла для выбора:

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

select () должен знать количество дескрипторов файлов, которые он должен просматривать.

...