Как отключить буферизацию в fread ()? - PullRequest
6 голосов
/ 02 января 2012

Я читаю и пишу в сокеты, используя fread () и fwrite (). Я полагаю, что эти функции предназначены для буферизованного ввода и вывода. Есть ли способ отключить буферизацию при использовании этих функций?

Редактировать:

Я создаю приложение для удаленного рабочего стола, и удаленный клиент, похоже, "немного отстает от сервера", и я понятия не имею, в чем может быть причина ... Я думал, что это может быть из-за буферизованного чтения и написать .. но с помощью setvbuf не сработало.

Под «отставанием» я подразумеваю, что клиент удаленного рабочего стола работает на несколько секунд позади сервера. То, что сервер делает в определенный момент, отражается на стороне клиента после задержки в 15-20 секунд.

Кроме того, я не хочу не использовать-fread (), потому что это часть существующего кода. Я не хочу изменять это. Я мог бы в конечном итоге использовать write () и read (), но хотел бы избежать этого.

Ответы [ 3 ]

8 голосов
/ 02 января 2012

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

setvbuf(fp, NULL, _IONBF, 0);

РЕДАКТИРОВАТЬ

Смешивать сокеты со стандартным вводом довольно сложно, как предупреждает Стивенс.Вот несколько цитат.

Проблема с этими тремя последними функциями [fseek, fsetpos, rewing] заключается в том, что все они вызывают lseek, который завершается ошибкой в ​​сокете.

Самый простой способ справиться с этой проблемой чтения-записи - это открыть два стандартных потока ввода-вывода для данного сокета: один для чтения и один для записи .

Один способ обойти эту проблему [проблема буферизации] принудительно заставляет выходной поток буферизоваться строкой, вызывая setvbuf.Другой - принудительно выводить каждую отраженную строку, вызывая fflush после каждого вызова fputs.Но на практике любое из этих решений по-прежнему подвержено ошибкам и может плохо взаимодействовать с алгоритмом Нагла


В заключение:

Попробуйтепрекратить использование stdio. Нет смысла использовать stdio и fread и fwrite.Вместо этого используйте прямые read и write.Стивенс говорит о «линейном буферизированном» выводе, потому что люди используют fgets и fputs со stdio

2 голосов
/ 02 января 2012

Использование

int setvbuf ( FILE * stream, char * buffer, int mode, size_t size );

mode
    Specifies a mode for file buffering:
    _IOFBF  Full buffering: On output, data is written once the buffer is full. On Input the buffer is filled when an input operation is requested and the buffer is empty.
    _IOLBF  Line buffering: On output, data is written when a newline character is inserted into the stream or when the buffer is full, whatever happens first. On Input, the buffer is filled up to the next newline character when an input operation is requested and the buffer is empty.
    _IONBF  No buffering: No buffer is used. Each I/O operation is written as soon as possible. In this case, the buffer and size parameters are ignored.

, определенное в stdio.h

1 голос
/ 02 января 2012

Под «отставанием» я подразумеваю, что клиент удаленного рабочего стола работает на несколько секунд позади сервера.То, что сервер делает в определенный момент, отражается на стороне клиента после задержки в 15-20 секунд.

Вам необходимо 100% подтвердить две вещи.

1) Клиент заблокирован в fread?Если нет, то это отстает, потому что он слишком занят, чтобы не отставать от сервера (или код сломан и тупо не вызывает fread).В любом случае буферизация и сеть не являются ошибочными.

2) Получил ли клиент меньше общих байтов от своих завершенных вызовов на fread, чем сервер отправил в своих завершенных вызовах на fwrite?Если нет, то это «отстает», потому что он неправильно понял некоторые данные, которые он получил (не смог понять, что он получил некоторые данные, которые он на самом деле получил).В этом случае буферизация и сеть не являются ошибочными.

Я поставлю вам с вероятностью 10 к 1, что одна из двух вещей, которые я упомянул выше, является случаем.

Чтобы прояснить случайдва, если неясно, рассмотрим этот пример:

1) Сервер отправляет сообщение.

2) Сервер отправляет сообщение.

3) Клиент вызываетfread и получает оба сообщения, но из-за неработающего кода думает только, что получил одно.(Возможно, неработающий код предполагает, что сообщения не могут «слипаться».)

4) На этом этапе может показаться, что клиент «отстает» от сообщения, но на самом деле код клиента простосломана.Клиент прочитал столько байтов, сколько отправил сервер.Это не отстает, просто сломан.

Пока вы не исключите эти два случая типа «занятый код» и «сломанный код», вы не должны предполагать, что сеть виновата, так как это наименее вероятное объяснение.

...