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.

AnkurVj
  • 7,958
  • 10
  • 43
  • 55

3 Answers3

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

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • so it will effect the behaviour of fread as well ? I did stumble upon this function but couldnt understand if this would work with fread – AnkurVj Jan 02 '12 at 09:53
  • 1
    @AnkurVj It should affect all stdio operations (i.e. everything using a `FILE *`). – cnicutar Jan 02 '12 at 09:54
  • 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 ? – AnkurVj Jan 02 '12 at 09:56
  • 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 – AnkurVj Jan 02 '12 at 09:57
  • 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? – David Schwartz Jan 02 '12 at 10:01
  • @DavidS I have added some description to the question – AnkurVj Jan 02 '12 at 10:06
  • @cnicutar 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. – AnkurVj Jan 02 '12 at 10:09
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

Fredrik Pihl
  • 44,604
  • 7
  • 83
  • 130
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.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • 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 execcution – AnkurVj Jan 02 '12 at 10:20
  • 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.) – David Schwartz Jan 02 '12 at 10:23
  • So, the question is this: When the client is lagging, *what* is it doing? Is it blocked in `fread`? – David Schwartz Jan 02 '12 at 12:34
  • 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 reason – AnkurVj Jan 04 '12 at 07:14
  • 1
    @AnkurVj You could log and timestamp when it enters `fread` and when it returns from `fread`. You could use profiling tools like `callgrind`. – David Schwartz Jan 04 '12 at 22:18