views:

198

answers:

3

Right now, I'm programming the networking for my online game, and I'm not really sure what to do about receiving data. The problem is that I can't really guess the packet's size, so I thought of reading just 4 bytes from the packet and converting them to an int to know what's the packet's size. Then I'll just create a buffer in that size and receive the rest of the packet, is that a good idea?

For your information, I'm using non-blocking i/o.

+2  A: 

Your approach sounds reasonable - you would essentially be embedding message size into a message header, which is likely the most robust way to handle it in your situation. Alternatively you could either use fixed length packets (ick) or use some sort of delimeter character (which will NOT work well at all for binary messages).

This link socket-protocol-fundamentals has some additional information which might help.

Justin Ethier
These two methods (size prefix, and end-delimiter) are the standard ways of handling this problem.
caf
A: 

If you are using TCP sockets, NEVER rely on packet size. The data flow is a stream of bytes, not a stream of packets.

Giuseppe Guerrini
I am using TCP sockets, what do you mean by that? (sorry for being foolish)
Tamir
Right, you should rely on message size specified in your header. Packet size is irrelevant, except to be aware that it can be smaller than your message (in other words, a message can arrive across multiple packets)
Justin Ethier
Sorry, I have misunderstood completely your question. And I'll remove my completely off-topic answer quickly. You were not talking about "network packet size", but instead "application packet size". The problem with TCP is that the networking may split your"logical" packet into slices, so the receiver must recompose them again.Bye
Giuseppe Guerrini
Ah, I see, no problem.Thanks alot Justin.
Tamir
(too many comments -- too late to delete my answer! -- shame on me!)
Giuseppe Guerrini
A: 

If you aren't careful, what you are proposing is a security hole in the making. So be very cafeful - especially when trusting network input.

You didn't specify TCP or UDP, so I'll just give you some general guidance.

For TCP or UDP, just allocate a single buffer of size N, where N is the biggest message size you could possibly have sent from the remote player or server. For UDP, I'd recommend keeping this under 1500 bytes. For TCP, you could have larger sizes.

For your socket, whether UDP or TCP, make it non-blocking. This is so you don't hang the game loop while waiting for data.

Add a size and crc-hash to the header of any message. When you receive the messsage as a UDP packet, if the size in the packet header is bigger than N (which means you've already got a truncated packet) or the hash doesn't match what you compute on the receive size, just reject the packet. I call this out because without additional integrity checks, hackers and cheaters will exploit your packet structure to win.

For TCP, you essentially frame your messages as the way you describe. Each message has a header dictating the number of bytes that are to follow. But do the same stuff as I call out for UDP - add a header of your own for integrity checking. Close the socket if you ever get message corruption and ASSERT.

In TCP, because of TCP segmentation, you may not receive the entire message in the same "recv" call. That is, if you only received a partial message, store it in temporary buffer. On a subsequent call to recv (on the next game frame), append to this buffer. You'll have to keep variables to track the expected end of the message so you don't accidentally read into the next message that may have been sent.

Good luck.

selbie