проверьте, не заблокирует ли fgets - PullRequest
3 голосов
/ 29 апреля 2010

Мне было просто интересно, можно ли в C заглянуть во входной буфер или выполнить аналогичный трюк, чтобы узнать, будет ли вызов fgets блокироваться позднее. Java позволяет делать что-то подобное, вызывая BufferedReader.ready (), таким образом я могу реализовать консольный ввод примерно так:

while (on && in.ready()) { 
  line = in.readLine();
  /* do something with line */
  if (!in.ready())
    Thread.sleep(100);
}

это позволяет внешнему потоку корректно отключить входной контур, установив значение false; Я хотел бы выполнить аналогичную реализацию в C, не прибегая к непереносимым трюкам, я уже знаю, что могу создавать «тайм-ауты fgets» под unix, прибегая к сигналам или (лучше, хотя и позаботясь о буферизации) переопределению это поверх recv / select, но я бы предпочел что-то, что будет работать и на windows.

ТИА

Ответы [ 2 ]

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

Рекомендуется использовать процедуры ввода-вывода сокета, предпочтительно poll () с требуемой миллисекундой в качестве тайм-аута, и в конечном итоге вы можете интерпретировать тайм-аут (возвращаемое значение = -1) как недоступность данных во входном буфере.
На мой взгляд, для достижения этой функциональности не существует неблокирующей стандартной функции ввода / вывода.

0 голосов
/ 29 апреля 2010

Я не уверен, о чем ты говоришь: сокет или дескриптор файла?

Для файлов не должно быть блокировок. Функция немедленно возвращается (кроме самого вызова I / O).

Для сокетов - вы можете использовать функцию ioctlsocket: Следующее говорит, есть ли ожидающие данные rcv:

ULONG nSize;
ioctlsocket(sock, FIONREAD, &nSize);

Следующее переводит сокет в неблокирующий режим:

ULONG nEnable = 1;
ioctlsocket(sock, FIONBIO, &nEnable);

В неблокирующем режиме - функции на сокете никогда не блокируются. Если они не могут выполнить запрос, они возвращают ошибку, и код ошибки WSAEWOULDBLOCK

Кроме того, в Windows существуют десятки гораздо более эффективных методов. Это:

  • Использование перекрывающегося ввода-вывода. Это нетривиально, но дает превосходную производительность
  • Связывание сокета с ожидаемым событием. Это переводит сокет в неблокирующий режим, плюс указанное событие сигнализируется, когда происходит сетевое событие.
  • Свяжите это с дескриптором окна. Это удобно для программ, ориентированных на пользовательский интерфейс.
...