The online racing simulator
Proper TCP buffer handling example (C#)
Hi,

I have seen many version of C# code that should handle a TCP buffer on this forum, but as far as I could see, none of them worked properly. A TCP buffer can have multiple packets or partial packets in 1 batch, and not any version I saw could handle them properly. So I wrote some code that is uncrashable and works with any buffer size, even a 1 byte buffer. I included an example. I just thought it might be helpful. Comments and improvement suggestions are welcome.

Thanks,
Ron
Attached files
tcpbufferhandling.rar - 10.3 KB - 1344 views
A big thank you T-RonX, This has helped me a lot. As you have probley seen, I have been stuck on this for a few days now. So thank you!
Quote from T-RonX :Hi,

I have seen many version of code that should handle a TCP buffer on this forum, but as far as I could see, none of them worked properly.

I wonder if you would care to elaborate on why the other code samples don't work properly, and what the difference is between them and the code you've posted is?

I ask this as I posted some code the other day that is, in my opinion, a great deal simpler than yours, which I use in many apps without problems. It also handles multiple packets, partial packets and will work with a 1 byte buffer.

I'm not saying that it isn't flawed, it may well be, but I'd like to be enlightened as to what that flaw may be.
I'v tested it and it works very well indeed. Actually it works pretty much the same way as my code. So there nothing wrong there, but other code sample are bad, or just working wrong. Even LFSlib has can't handle a low buffer size.
Quote from T-RonX :I'v tested it and it works very well indeed. Actually it works pretty much the same way as my code. So there nothing wrong there, but other code sample are bad, or just working wrong. Even LFSlib has can't handle a low buffer size.

OK cool. You had me worried for a minute there.
I wanted to nerco-bump this topic as I have been thinking about this issue, and the more I learn about sockets, the more I realise that this doesn't matter. It doesn't matter if your buffer code cannot deal with a buffer size of 1, because you should never set your buffer that low anyway. LFSLib is mentioned here as being broken, but in reality the buffer code in that library follows the same semantics as almost every other example I've seen, which is that the buffer must be at least as large as the largest packet.

Yes you can use generic-lists or crazy array copying strategies to allow your program to deal with extremely small buffer values, but the fact is that doing so sacrifices efficiency, and as you should always keep the buffer size reasonably large (Microsoft recommends 2mb+), it should have no impact on how your code actually runs (Edit: if your packets are larger than 2mb, you should consider splitting them into smaller packets).

If your code requres the buffer to be at least as large as the largest packet, this is the solution:

assert(BUFFER_SIZE >= MAX_PACKET_SIZE);

My InSim code cannot deal with a buffer size of 1. That doesn't mean that the code is broken, or that I'm a bad programmer, it just means I should never set the buffer size to 1.

Anyway... pointless nerco rant over.
Personally I don't think it matters if you should set it the buffer to 1 or not. I like code to be rock solid and fool proof.

However this code is already outdated and in the new version of LFS External (which takes ages I know...) I have a totally different setup for receiving and parsing packets. I can now receive packets in a somewhat parallel order, and the code for parsing is much less. like:


// Add data to stack
Array.Resize(ref data, size);
stack.AddRange(data);

// Add complete packets
while (stack.Count >= nextPacketSize)
{
packets.Add(stack.GetRange(0, nextPacketSize).ToArray());
stack.RemoveRange(0, nextPacketSize);
if (stack.Count > 0) nextPacketSize = stack[0];
}

I'm now a professional web app dev so I have to write good code and understand how important it is, and not just take the easy way out.

And I also think for learning purposes it's better to go the correct way. And I think, in this case, the correct way is allowing 1 byte buffers.

FGED GREDG RDFGDR GSFDG