чтение из stdin с помощью select() — неблокирующим способом

#c #linux #stdin #nonblocking

#c #linux #стандартный интерфейс #неблокирующий

Вопрос:

я пишу программу, которая выполняет отношения сервер-клиент.
В программе я использую select() для того, чтобы получать запросы клиента, а также запросы пользователя (тот, что находится за сервером) из stdin.
Похоже, что select() это нормально работает для запросов клиента, но, похоже, не реагирует на ввод от stdin .
Кроме того, мне не удается recv() из stdin . Есть ли способ получить входные данные из stdin неблокирующим способом? Я пытался использовать fgets() вместо select() , и хотя я установил fcntl() неблокирующим, похоже, это не работает — оно все еще блокируется.

Что вы предлагаете? Спасибо.

Комментарии:

1. Можете ли вы опубликовать какой-нибудь код, основанный на том, как вы пробовали?

2. winsock означает Windows? 😉 Я думал, что select () предназначен только для сокетов в Windows, обработчики файлов не могут быть обработаны с помощью select, но это возможно в Unix, где вы могли бы получить дескриптор файла и добавить его в FD_SET

3. К чему подключен stdin: к обычному файлу? канал? сокет? Как это открывается? Попробуйте опубликовать небольшую программу, в которой обнаруживается проблема.

Ответ №1:

stdin буферизован по строкам — вы не можете читать из него неблокирующим способом.

Комментарии:

1. Буферизация строк является функцией потоков стандартной библиотеки C или C и не имеет значения на уровне системных вызовов ввода-вывода POSIX, таких как recv() и select() . Что касается stdin вопроса, прочитайте STDIN_FILENO , если это поможет.

Ответ №2:

Вы всегда можете использовать kbhit, чтобы посмотреть, есть ли какие-либо символы во входном буфере, готовые к чтению.

На случай, если у вас нет доступа к kbhit , вот простая реализация, которую я использовал в прошлом:

 int kbhit() {
   int count = 0;
   struct termios otty, ntty;
   tcgetattr(STDIN_FILENO, amp;otty);
   ntty = otty;
   ntty.c_lflag amp;= ~ICANON;
   if(tcsetattr(STDIN_FILENO, TCSANOW, amp;ntty) == 0) {
      ioctl(STDIN_FILENO, FIONREAD, amp;count);
      tcsetattr(STDIN_FILENO, TCSANOW, amp;otty);
   }
   return count;
}