Advertisement

Input/Output Processing From Sockets

Started by April 13, 2006 05:35 PM
13 comments, last by _winterdyne_ 18 years, 9 months ago
I'm interested in tutorials or helpful sites on what to do with input/output. I can send/recv just fine, but I'm unsure on how to go about keeping the input buffers from overflowing. What I've got so far is to look through the whole input buffer from the beginning until I find a '\n' or '\r' and sending that out for processing. How would I go about moving the rest of the stuff inside the buffer forward so that I can keep from getting overflow. My other problem is, what happens if the user enters more text than the input buffer can handle at once? As far as handling output, what do I need to do here to insure that the socket gets all the output for one command if its bigger than the output buffer? I'm not sure that that would come up, but in case it does? Oh, and this is for a MUD server I'm trying to write. For me, this is the hardest stage. All the output/input is text.
The classic approach to prevent overflow is to split the message into packets of a size less than the transmission unit, and reassemble it at the other end.
Winterdyne Solutions Ltd is recruiting - this thread for details!
Advertisement
Computers have finite amounts of memory. No matter how big you make a buffer, it is technically possible to attempt to overflow it. Here are your options:

1) block everything until the buffer drains
2) throw away the extra data

I would recommend 2) on the server, because 1) would allow a user to lock up your server. I would recommend 1) on the client, because it makes correctness easier.
enum Bool { True, False, FileNotFound };
Quote:
Original post by redshift86
I'm interested in tutorials or helpful sites on what to do with input/output. I can send/recv just fine, but I'm unsure on how to go about keeping the input buffers from overflowing.

What I've got so far is to look through the whole input buffer from the beginning until I find a '\n' or '\r' and sending that out for processing. How would I go about moving the rest of the stuff inside the buffer forward so that I can keep from getting overflow.


Once you find your end of line character, use memmove to shift the rest along to the start. Or just loop through moving a character at a time. Make sure you keep track of where the new end of the buffer is (it will be wherever it was before minus whatever you just removed, obviously).

Quote:
As far as handling output, what do I need to do here to insure that the socket gets all the output for one command if its bigger than the output buffer? I'm not sure that that would come up, but in case it does?


Put as much as you can into the buffer, send it, then get the next bit, send that, until you have no more to send. It's trivial when you think about it! :)
Thanks for the help guys. I decided to go with moving each character, and its working great.
Quote:
Original post by Kylotan
Quote:
Original post by redshift86
I'm interested in tutorials or helpful sites on what to do with input/output. I can send/recv just fine, but I'm unsure on how to go about keeping the input buffers from overflowing.

What I've got so far is to look through the whole input buffer from the beginning until I find a '\n' or '\r' and sending that out for processing. How would I go about moving the rest of the stuff inside the buffer forward so that I can keep from getting overflow.


Once you find your end of line character, use memmove to shift the rest along to the start. Or just loop through moving a character at a time. Make sure you keep track of where the new end of the buffer is (it will be wherever it was before minus whatever you just removed, obviously).



This can be horribly inefficient. Instead of moving, track the start point of the 'allocated' block in the buffer and move it forward. You will also need a 'wrap flag', a read offset and a write offset. When a block to be queued is added to the buffer, it is, if possible added contiguously to the existing block (at the end). If the block will not fit, it should be added to the start of the block but should not overwrite the read offset. This is a typical 'circular buffer' trick. Providing you can retrieve the data fast enough (incrementing the read) before the write offset catches up this provides a fast, efficient, reduced-overflow buffer. It is however susceptible to failed adds when numerous large blocks are being added. This is alleviated by increasing the buffer size.

For a MUD server, you do really want to look at a packet queue system, especially if you're planning on expanding the codebase to a custom client, rather than telnet.
Winterdyne Solutions Ltd is recruiting - this thread for details!
Advertisement
Quote:
Original post by _winterdyne_
This can be horribly inefficient.

Oh, of course, but he did say this was for a MUD server. The incoming bandwidth is unlikely to exceed 1K a second, if that. :) I'd prefer not to give out the complex but efficient advice to begin with.
Quote:
Original post by Anonymous Poster
and instead of a buffer overflowing in a dangerous way that overwrites the stack, the worst that can happen with a ring buffer is that unread data is overwritten.


That's simply not true. There's no difference between reading into a ring buffer or any other buffer. You still have to know exactly how many bytes it is safe for you to place in the buffer, or you'll trash whatever comes after it, being the rest of the buffer, and/or anything else.
Yes, if you're using a ring buffer it's a really good idea to wrap reads and writes to/from it into functions that perform proper bounds checking.


Winterdyne Solutions Ltd is recruiting - this thread for details!
Quote:
Original post by _winterdyne_
For a MUD server, you do really want to look at a packet queue system, especially if you're planning on expanding the codebase to a custom client, rather than telnet.


Would that just be like polling all sockets first, adding complete packets to the que, and then processing the packets in the que?

This topic is closed to new replies.

Advertisement