🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Enet sends packets at a very slow rate.

Started by
4 comments, last by Kylotan 1 year, 11 months ago

So I am programming the multiplayer part of my RTS game with Enet. After I was able to send important data, I realized that my packets are taking forever to get from the client to the server… although they are running from localhost. I have not been able to find any information regarding a possible fix to this, so I will just go ahead and post any code more that might be needed to help me solve the problem.

So here is what I currently am sending:

struct PlayerStatePacket {
	int posX[500];
	int posY[500];
	int posZ[500];
	int teamNo[500];
};

This is the struct that is being sent with the packet. Each individual packet is intended to account for each and every unit that is on the game battlefield. I use this method because all of the units are in a vector, and it iterates through this vector when the rendering and unit selection is done… and now that list also includes the packets that are being sent. Moreover, the positions are set and sent like so:

clientInstance.playerStatePacketVariable.posX[i] = units[i].positions.x;
clientInstance.playerStatePacketVariable.posY[i] = units[i].positions.y;
clientInstance.playerStatePacketVariable.posZ[i] = units[i].positions.z;

And this is done for every frame.

I have done some testing, and I have found that sending the packet for every iteration in every frame slows the game down drastically, though I kind of saw that one coming…

But however, that leads me to believe that something is clogging up the information that is being sent over from the client to the server.

Either that or there is some stupid timer that I forgot to account for.

Anyone here have any ideas as to what I might be doing wrong?

Thank you!

-rydog

Advertisement

Your struct is 2000 ints, or 8000 bytes.

The typical MTU, or Maximum Transmission Unit, is 1500 bytes and a portion of that is taken by your routing overhead. Enet is probably breaking up the data and managing how the chunks flow, further adding to the traffic.

And you write you are sending it every frame, presumably 60 frames per second but on fast hardware maybe 90, 120, 144, or even more frames per second.

A half megabyte (or more) per client every second, and that is just for that structure alone. You probably have additional data, too.

While two of these probably won't saturate a fast connection, it is a tremendous volume of data. More than a handful of clients will saturate the network and lead to all sorts of problems.

Transmit less, look at more efficient encodings, and/or look at other ways to send what you need more efficiently. For example, transmit state changes and occasional checkpoints rather than continuous positioning data, consider protocol buffers (protobufs) and compression, along with investigating better streaming data protocols if you can't get the encoding down to small sizes.

Enet has some built in rate limits (search for “throttle,”) and also some built in metrics you can read on the EnetPeer (things like “bandwidth”)

I recommend you consider those limits, and also print those metrics, to see what's going on. Also, Enet was built in a day when 100 Mbps network connections were not the standard, so it's tuned for much smaller packets. RakNet is a little higher performance for very large packets (it does disassembly/reassembly using bulk transfer methods) but it's just not a good idea to send megabytes of data per second for a real-time interactive game.

Separately, RTS games typically end up with the “deterministic lockstep" simulation model, because that's the best way of making sure that you can do hundreds of units, while not using megabytes per second of bandwidth. You might want to google for the “1500 archers on a 28800 modem” article about the Age of Empires networking model, which is a good introduction to this approach.

enum Bool { True, False, FileNotFound };

@hplus0603 and @frob I figured out the issue. While I did find your articles to be useful, I discovered that I had initialized the client with a BPS cap, and, after doing more research, when something hits the BPS cap, then it piles up until it has enough space to send it eventually.

Yep, that's literally what the cap is there for, to place a hard limit on your bandwidth usages. That's what hplus0603 meant by the rate limits and the throttle values.

While setting that to a more reasonable value is essential, you should still consider the advice above, because currently you're sending too much data, too frequently. You will probably be able to reduce the size of the struct by using better data types and you probably don't need to send every frame either.

This topic is closed to new replies.

Advertisement