How do I disable buffering in fread()?
Asked Answered
L

3

7

I am reading and writing to sockets using fread() and fwrite(). These functions, I believe are for buffered input and output. Is there some way that I can disable buffering while still using these functions ?

Edit :

I am building a remote desktop application and the remote client seems to be "lagging a bit behind the server", and I dont have any idea what may be the reason... I thought it may be because of buffered read and write .. but using setvbuf didnt work.

By "lagging", I mean that the remote desktop client is running a few seconds behind the server. What the server is doing at a particular moment is reflected on the client side after a delay of some 15-20 seconds.

Also, I dont want to not-use-fread(), because it is a part of existing code. I don't want to modify it. I could eventually use write() and read(), but I would like to avoid it.

Linell answered 2/1, 2012 at 9:49 Comment(5)
really, some sort of comment would be appreciated if you are going to downvoteLinell
I didn't understand the downvote, either. +1Aegean
i have faced the same problem in past but didnt think of disabling that..!! so +1Actinon
Note that you can also simply call fflush() after you've written something (or a batch of something) to transfer the buffers to the socket.Mineralogist
@Mineralogist I will definitly try that and see if it solves my problem.Linell
B
8

You can use setvbuf to disable buffering for a specific file pointer:

setvbuf(fp, NULL, _IONBF, 0);

EDIT

Mixing sockets with standard input is kind of tricky, as warned by Stevens. Here are a few quotes.

The problem problem with these latter three functions [fseek, fsetpos, rewing] is that they all call lseek, which fails on a socket.

The easiest way to handle this read-write problem is to open two standard I/O streams for a given socket: one for reading and one for writing.

One way around this [buffering problem] is to force the output stream to be line buffered by calling setvbuf. Another is to force each echoed line to be output by calling fflush after each call to fputs. But in practice, either of these solutions is still error-prone and may interact badly with the Nagle algorithm


In conclusion:

Try to stop using stdio. It makes no sense to use stdio and fread and fwrite. Use straight read and write instead. Stevens speaks of "line buffered" output because people use fgets and fputs with stdio

Burdensome answered 2/1, 2012 at 9:52 Comment(7)
so it will effect the behaviour of fread as well ? I did stumble upon this function but couldnt understand if this would work with freadLinell
@Linell It should affect all stdio operations (i.e. everything using a FILE *).Burdensome
The reason I ask is because I tried it in my program, and it doesn't seem to work. Is there some other reason why a client might lag behind a server ?Linell
I am building a remote desktop application and the remote client seems to be lagging a bit behind the server, and I dont have any idea what may be the reason... I thought it may be because of buffered read and write .. but using setvbuf didnt workLinell
It would help if you described the actual problem you are trying to solve. What does it mean for the client to be "lagging behind the server"? Is the client blocked in fread and has not received as many bytes as the server has passed to calls to fwrite that have returned?Frauenfeld
@DavidS I have added some description to the questionLinell
@Burdensome I dont want to not-use-fread(), because it is a part of existing code. I don't want to modify it. I could eventually use write() and read(), but I would like to avoid it. I Maybe i will try replacing it once and see if it actually makes a difference.Linell
H
2

Use

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.

defined in stdio.h

Husted answered 2/1, 2012 at 9:53 Comment(0)
F
1

By "lagging", I mean that the remote desktop client is running a few seconds behind the server. What the server is doing at a particular moment is reflected on the client side after a delay of some 15-20 seconds.

You need to 100% confirm two things.

1) Is the client blocked in fread? If not, then it's lagging because it's too busy to keep up with the server (or the code is broken and is stupidly not calling fread). In either case, buffering and the network are not at fault.

2) Has the client received fewer total bytes from its completed calls to fread than the server has sent in its completed calls to fwrite? If not, then it's "lagging" because it has misunderstood some of the data it received (failed to realize that it got some data that it actually got). In that case, buffering and the network are not at fault.

I will bet you at 10 to 1 odds that one of the two things I mentioned above are the case.

To clarify case two in case it's not clear, consider this example:

1) The server sends a message.

2) The server sends a message.

3) The client calls fread and gets both messages but due to broken code, only thinks it has gotten one. (Perhaps broken code assumes that the messages cannot get 'stuck together'.)

4) At this point, it may seem that the client is "lagging" by a message, but actually, the client's code is just broken. The client has read as many bytes as the server has sent. It is not lagging, just broken.

Until you rule out these two "busy code" and "broken code" type cases, you should not assume the network is at fault, since that's the least likely explanation.

Frauenfeld answered 2/1, 2012 at 10:13 Comment(5)
2) The client cannot miss messages because it would immediately fail if it does. (The construction is such). So I'm 100% sure it's not missng messages. 1) By blocking, are you referring to the concept of blocking and non-blocking calls ? my fread() is blocking in the sense that the program doesnt proceed until it has read the specified number of bytes. Also, there is only a single thread of execcutionLinell
By blocking, I mean the execution of the thread is stalled because it is in an fread call, waiting for data. If it's not waiting for data, then the lag is probably caused by whatever it's doing rather than waiting in fread for data. (By the way, I'd just suggest not using fread for sockets anyway. It adds complications and has no real benefits.)Frauenfeld
So, the question is this: When the client is lagging, what is it doing? Is it blocked in fread?Frauenfeld
David, How do I find out where is it spending its time? Also, I should mention that currently server and client are both running on the same physical machine .. so network lag should not be a reasonLinell
@Linell You could log and timestamp when it enters fread and when it returns from fread. You could use profiling tools like callgrind.Frauenfeld

© 2022 - 2024 — McMap. All rights reserved.