#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;
}