🔒 Locked
String or Objects?
Advertisement
Original Post
Hey, i'm wondering what a good solution would be to send certain things over a TCP network. We are currently trying to create the basics of a multiplayer game (more like a MMO style game), but we're not sure if it's better to send strings or objects. With strings we can use our own protocol. Suppose we send the following string: 8:x21:y50:z50:r45.13234:ani2 Which represents the following: 8 = ID of the player you can guess what x, y, and z are for r = the rotation value of the current player in the world ani = the animation to be played. This string can be easily split up by the server/client. This is how we do it right now. But some of us think it's better to send objects instead of strings... So what do you recommend to use, strings or objects? Some additional info: We use a TCP connection We are programming in C# We use the Socket library, NOT StreamWriter I'm wearing blue socks.
First of all, I am by no means an expert of C#. However, I have a fair amount of experience implementing MMORPG protocols over both TCP and UDP. My primary concern regarding the string format is that you will need to have a way of separating data sent in individual send() calls. TCP is a stream protocol -- as such, there is no guarantee that the data sent using send() is the same as that received in recv(); you may very well receive a part of a message, or even two at once. In binary protocols, this issue is usually tackled by letting the two first bytes represent the length of the packet. Then you enter a receiving loop where you receive until you have the required amount of bytes. This could be accomplished using some form of message separator in the text, such as a newline character.
If you ask me I'd definitely say use the binary method. Reasons:
- If you are making an MMO, bandwidth usage should be kept as low as possible. It costs a shitload of money.
- If you use the string method, separating the elements and converting them to machine-friendly data will bog down the server process and prevent your system from scaling!
- Text-based protocols tend to be easier for hackers to make sense of. This could allow for easy creation of server emulators and cheats.
- No MMORPG that I know of uses a text-based protocol.
If you ask me I'd definitely say use the binary method. Reasons:
- If you are making an MMO, bandwidth usage should be kept as low as possible. It costs a shitload of money.
- If you use the string method, separating the elements and converting them to machine-friendly data will bog down the server process and prevent your system from scaling!
- Text-based protocols tend to be easier for hackers to make sense of. This could allow for easy creation of server emulators and cheats.
- No MMORPG that I know of uses a text-based protocol.
Quote:
separating the elements and converting them to machine-friendly data will bog down the server process
I doubt you'd be able to trace the difference in a profiler. Let's assume you have a 10 Mbit/s input. That's 1.2 Mbyte/s of actual data. A modern CPU can chew through 20 Gbyte/s of data -- that's a factor 20,000 between networking data rate and CPU data rate. If your CPU spent more than 1/1000th of its time parsing your network packets (as opposed to doing simulation, etc), then you're doing something wrong, no matter what the encoding.
Quote:
and prevent your system from scaling
System Performance asks the question: "How many users can I serve from this one server unit?"
Scalability asks the question "How many additional users can I serve by adding one additional server unit?"
Whether your messages are text or binary does not affect scalability at all. It may affect performance, but mostly for your networking infrastructure (switching hardware, firewalls, etc).
Well, we're using strings because they are easy to use, and we don't have to worry for any hackers right now and that sort of stuff.
Before we send the string, we convert it to bytes like so:
string msg = "initpos:5:x20:y30:z40";
byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);
Until now we had no problems with sending and receiving data.
I use socket.EndReceive to ensure all data is in.
I guess this seems like we can safely continue for now with what we were doing.
Before we send the string, we convert it to bytes like so:
string msg = "initpos:5:x20:y30:z40";
byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);
Until now we had no problems with sending and receiving data.
I use socket.EndReceive to ensure all data is in.
I guess this seems like we can safely continue for now with what we were doing.
Quote:
Original post by Anon Mike
As mentioned the disadvantage is mostly bandwidth.
Bandwidth is merely channel capacity. If one needs to send 200kbits/sec of information over 3kbit/sec channel no encoding will suffice.
Encoding in general represents the constant factor. There's still many cases today where a factor of 2 means a difference in either usability or savings, but for any non-trivial problem other factors will determine actual required capacity, such as rate of updates.
Of course, text stream can optionally be compressed, for small messages just Huffman coder will do surprisingly well, and that's a completely separate part that's independent of content. Huffman coding text can actually result in less data being sent under some circumstances (consider vector of 3 floats: "5.7,7.5,7.7"), where even the plaintext is shorter than binary form.
There's no reason why one couldn't pass semantically rich (XML et al) stream that is encoded based on client's preference.
Primary choice about encoding should involve whether the contents benefit from being in human readable form. XML is standard in effectively all enterprise systems simply because it's structured, self-describing and can be manipulated by third-parties in a loosely coupled fashion.
But considering this is about C#, serialization is basically a non-issue, and should be configurable to support emitting either binary, plaintext or structured data. Any additional metadata can always be omitted, so adding it from start makes sense.
Quote:
I guess this seems like we can safely continue for now with what we were doing.
IMHO, in line with previous paragraph, use the C#'s facilities for serialization. Manually constructing fields is not viable and will make maintenance a nightmare.
(consider vector of 3 floats: "5.7,7.5,7.7"), where even the plaintext is shorter than binary form.
Assuming you send floats totally uncompressed, a triple like that takes 12 bytes.
For the string, I count 12 bytes (including the terminating character).
How is that shorter?
Btw: 0.7" has no exact representation, so unless you legislate that all data is rounded to one-tenth precision only, your update of 0.7, when generated out of a float to string, may very well look something like 0.6999999 or 0.7000001; again, if you don't force rounding to some width.
If compressing floats to fix16, (say, s10.5 format for worlds with extent -1000..1000 meters and ~inch position quantization) a binary triple is just 6 bytes.
And Huffman (or even LZ77!) can be used on binary packets, too, you know :-)
Quote:
Original post by hplus0603
Assuming you send floats totally uncompressed, a triple like that takes 12 bytes.
For the string, I count 12 bytes (including the terminating character).
Let's say there is no terminating character and the length is implied by UDP packet size or something.
Quote:
Btw: 0.7" has no exact representation, so unless you legislate that all data is rounded to one-tenth precision only, your update of 0.7, when generated out of a float to string, may very well look something like 0.6999999 or 0.7000001; again, if you don't force rounding to some width.
Quote:
And Huffman (or even LZ77!) can be used on binary packets, too, you know :-)
This is why I chose such numbers. Given the above string, there's only 4 distinct characters, while binary representation of these floats will result in considerably more distinct bytes.
My point was merely that data representation should depend on its intended purpose. Text configuration works just fine *nixes and makes lots of sense since humans interact with them.
If said protocol is meant to be internal, then there's no need to human readable representation, regardless of whether data is additionally compressed or not, making it binary on wire.
Well, at the risk of being pedantic, the majority of your code shouldn't care. Send objects at your network connection, and then have a serializer change them into a byte stream.
Best of both worlds - binary serialization for "real" and text serialization if you ever feel the need to do telnet-style debugging.
In general, I'd recommend binary serialization, but at the end of the day if performance is sufficient, then whatever works is fine. So long as you're not comparing binary data to something like SOAP, the difference in size probably isn't too horrendous, and you'll probably get more savings by not sending unnecessary data than by switching from text to binary.
Best of both worlds - binary serialization for "real" and text serialization if you ever feel the need to do telnet-style debugging.
In general, I'd recommend binary serialization, but at the end of the day if performance is sufficient, then whatever works is fine. So long as you're not comparing binary data to something like SOAP, the difference in size probably isn't too horrendous, and you'll probably get more savings by not sending unnecessary data than by switching from text to binary.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement