views:

32

answers:

1

Hi,

This is more of a design question than a specific code question, I'm sure I am missing the obvious, I just need another set of eyes.

I am writing a multi-client server based on WSAAsyncSelect, each connection is made into an object of a connection class I have written which contains associated settings and buffers etc.

My question concerns FD_WRITE, I understand how it operates: One FD_WRITE is sent immediately after a connection is established. Thereafter, you should send until WSAEWOULDBLOCK is received at which point you store what is left to send in a buffer, and wait to be told that it is ok to send again.

This is where I have a problem, how large do I make this holding buffer within each connections object? The amount of time until a new FD_WRITE is received is unknown, I could be attempting to send a lot of stuff during this period, all the time adding to my outgoing buffer. If I make the buffer dynamic, memory usage could spiral out of control if for whatever reason, I am unable to send() and reduce the buffer.

So my question is how do you generally handle this situation? Note I am not talking about the network buffer itself which winsock uses, but one of my own creation used to "queue" up sends.

Hope I explained that well enough, thanks all!

A: 

Naturally, the correct design depends on the nature of your application.

Some programs can predict the amount of data that can be generated before something must be done with it, so they can use a fixed-size buffer. One protocol I designed, for instance, had a command-response structure and a 2-byte length prefix, so I could use 64K buffers and know I'd never overflow them. If a buffer is full, the program must be waiting for a reply before it is allowed to send data from that buffer, so no more data will be added to that buffer.

Another good use for fixed-size buffers is when the data comes from another I/O source. Consider a web server: at its most basic, it slurps files from disk and spits them out on the wire. You therefore know how much you are reading from disk at a time, so you know how big your buffers must be.

I'm having trouble coming up with a good reason to use dynamic buffers.

The main reason you don't need them is TCP's sliding window. If one of the connection peers stops receiving data, the remote peer's stack will stop sending data when the TCP window fills up. The unread data will stay in the receiving stack's buffers until the program it was sent to requests it. This gives the receiver a way to throttle the incoming data to a level it can handle. As far as I can tell, that makes fixed-size buffers practical under all conditions.

Warren Young
Hi thanks for your answer. My application is set up similar, packets are defined as size-instruction-data, taking up to a maximum of 64k each, hence for receiving I can easily define a maximum buffer size.This leaves me with another question that I am unsure how to answer. It concerns the "buffer full" scenario, how do I handle this. If a user hits a button which would send a packet to the server, but this can't be completed because the buffer is full, my UI is not acting as expected. Am I left to wait until the user repeats the command?Thanks!
Xexr
I would build each outgoing packet as soon as you know how to create it, put it in a linked list, and have your FD_WRITE handler use these blocks to send from.
Warren Young
See, but a linked list is just managed dynamic memory - and not that dissimilar from my original approach. But thanks for your help, I will update my code to use linked lists rather than the custom solution I have right now.
Xexr