Jump to content

  • Log In with Google      Sign In   
  • Create Account

Overflowing Buffers!


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 Xanather   Members   -  Reputation: 708

Like
0Likes
Like

Posted 17 October 2012 - 03:05 AM

Context (if it matters): Creating a game networking system using C# and .net's TcpClient/NetworkStream (no network library).

The client and server programs both have two buffers, the upload buffer and the download buffer, both are 64kb in size (I am talking about application buffers here).

The download buffer is used for downloading available bytes on the network stream at the start of every game tick.
The upload buffer is used for sending all messages (within that game tick) at the end of every game tick.

Current problems I am experiencing is how to handle this all:
  • Currently the download buffer can easily overflow, if available bytes available on the stream are greater than the byte buffer (64kb) minus the current data stored in the byte buffer (due to possibly previous half messages received in previous ticks) then the buffer obviously overflows.
  • Another problem I have is the upload buffer, throughout a game tick messages are added to the upload buffer; which is then sent at the end of the game tick. If massive messages are sent within one game tick (greater than 64kb) then the upload buffer overflows.
Question(s): How can I handle the two dot points above? is overflowing buffers normal? (I remember playing gmod a few times and got the buffer overflow errors). Do I even need a upload buffer? should I just write directly to the stream once a message has been created during a tick?

Right now whenever I try sending even one chunk (containing tile data) from the server -> client the upload buffer overflows on the server and the download buffer would overflow on the client. I solved the problem by forcefully making the server send the upload buffer multiple times before the end of a game tick and making the client download the chunk over more than 1 tick (by checking if the buffer is close to overflowing when reading 256 byte increments from the stream during a tick). But I feel like I hackishly solved the problem and my code is no longer consistent.

All replies are appreciated, thanks.

Edit: I would read available bytes from the stream instantaneously as they arrive/are sent but each client is not assigned a thread. Also: sorry if I am asking too much :(

Edited by Xanather, 17 October 2012 - 03:09 AM.


Sponsor:

#2 Ripiz   Members   -  Reputation: 529

Like
3Likes
Like

Posted 17 October 2012 - 05:02 AM

Use bigger buffer or use dynamic buffer which increases everytime it overflows. Eventually it'll reach max size when it stops overflowing, however it might end up eating whole RAM if you have bug somewhere.

#3 Xanather   Members   -  Reputation: 708

Like
0Likes
Like

Posted 17 October 2012 - 05:12 AM

@Ripiz. Ok, I will try change the size to 1MB (which will allow for bits of world chunks). There is no other performance decrease in doing this except for more RAM usage right?

Edited by Xanather, 17 October 2012 - 05:24 AM.


#4 hplus0603   Moderators   -  Reputation: 5304

Like
2Likes
Like

Posted 17 October 2012 - 10:29 AM

Using a larger buffer uses more RAM, and, at the extreme, may cause heap fragmentation (you're a while away from that danger yet I think.)

The other problem with big buffers is that nothing else can be sent at the same time on that same stream. If you're using a single TCP connection for all game data, that means all chat, world movement, friend requests, and other such information is blocked by transferring the large amount of data. You might be better off defining a protocol that first establishes a chunk ("define chunk 123 to have size 800 kB") and then sends pieces of that chunk as packets ("here's the data for offset 324,000 size 2,000 for chunk 123") and finally, when all pieces are sent, sends the "use chunk" message.

enum Bool { True, False, FileNotFound };

#5 Xanather   Members   -  Reputation: 708

Like
0Likes
Like

Posted 18 October 2012 - 04:07 AM

That makes sense, your saying to use a complete different TCP stream (different port) or use UDP for tile chucks? Or during when the connection is being established between the server/client (handshakes etc..)?

Edited by Xanather, 18 October 2012 - 05:40 AM.


#6 hplus0603   Moderators   -  Reputation: 5304

Like
1Likes
Like

Posted 18 October 2012 - 11:23 AM

You can use another TCP stream -- you can even use HTTP for larger downloads; HTTP is a fine bulk data transfer protocol with lots of good infrastructure available.

What I was actually suggesting was that you time-slice the existing TCP stream, though. If you already have "packet types" over TCP (which I presume you do, else you're going to want to add that,) then you can define a number of smaller packets, which, when put together, transfer the entire large chunk of data. The benefit is that you can send different kinds of packets in between each fragment of the big file, so the entire connection doesn't appear to "freeze" while downloading one big thing.

enum Bool { True, False, FileNotFound };

#7 Xanather   Members   -  Reputation: 708

Like
0Likes
Like

Posted 18 October 2012 - 10:26 PM

Yes I do have prefixed messages types (byte) and message lengths (short).
Well, that makes sense, so just send parts of the chunk each tick? (and each tick chunk could have just one x row of the whole chunk?).

Also is there any point to having a application upload buffer? Should I write directly to the stream every time something happens (even if its just a chat message being sent)? I feel having the program upload everything in one tick is better to do than write several times (if not 20+ times) per tick.

thanks for your help hplus.

#8 hplus0603   Moderators   -  Reputation: 5304

Like
1Likes
Like

Posted 18 October 2012 - 10:47 PM

Yes, it's usually better to buffer all outgoing messages and send them in one fell swoop when the "tick time" comes. If you ever change to UDP, that's a requirement. For TCP, the OS will do some of that buffering for you, if you do not turn off Nagling (i e, do not turn on TCP_NODELAY.)
enum Bool { True, False, FileNotFound };

#9 Xanather   Members   -  Reputation: 708

Like
0Likes
Like

Posted 19 October 2012 - 02:40 AM

Ahhh, right, I have turned that off xD (in order to lower latency), so I'm going to stick to what I have.

thanks again Posted Image

Edited by Xanather, 19 October 2012 - 02:40 AM.


#10 Xanather   Members   -  Reputation: 708

Like
0Likes
Like

Posted 19 October 2012 - 08:57 AM

Done! Implemented it successfully (over several ticks) and it works like a charm with only 256kb application buffers :D.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS