tagh
tagh

Reputation: 1037

NodeJS + Socket IO Sends Too Much Data

I am currently developing a game using NodeJS + SocketIO but is having problem with the amount of data being sent. The server currently sends about 600-800 kbps which is not good at all.

Here are my classes:

Shape
    Pentagon
    Square
    Triangle
Entity
    Player
    Bullet

Every frame (60 fps), I update each of the classes and each class will have an updatePack that will be sent to the client. The updatePack is pretty simple, it only containts the object's id and coords.


At first, I thought everyone's game are like that (silly me). I looked into several simple games like agar.io, slither.io, diep.io, and rainingchain.com and found that they use < 100 kbps which made me realize that I am sending too much data.

Then I looked into compressing the data being sent. But then I found out that data are automatically compressed when sending in Socket.io


Here is how I send my data:

for(var i in list_containing_all_of_my_sockets){
    var socket = list_containing_all_of_my_sockets[i];
    data = set_data_function();
    socket.emit('some message', data);
}

How can I make it send less data? Is there something that I missed?

Upvotes: 1

Views: 1346

Answers (4)

dodov
dodov

Reputation: 5844

You could use arrays instead of objects to cut down some size (by omitting the keys). It will be harder to use the data later, but... you've got to make compromises.

Also, by the looks of it, Socket.IO can compress data too, so you can utilize that.

As for updating, I've made a few games using Node.js and Socket.IO. The process is the following:

  1. Player with socket id player1 sends his data (let's say coordinates {x:5, y:5})
  2. Server receives the data and saves it in an object containing all players' data:

    {
        "player1": {x:5, y:5},
        "player2": ...
        ...
    }
    
  3. Server sends that object to player1.

  4. player1 receives the object and uses the data to visualize the other players.

Basically, a player receives data only after he has sent his own. This way, if his browser crashes, you don't bombard him with data. Otherwise, if you've sent 15 updates while the user's browser hanged, he needs more time to process these 15 updates. During that time, you send even more updates, so the browser needs even more time to process them. This snowballs into a disaster.

When a player receives data only after sending his own, you ensure that:

  1. The sending player gets the other players' data immediately, meaning that he doesn't wait for the server's 60 times-per-second update.
  2. If the player's browser crashes, he no longer sends data and therefore no longer receives it since he can't visualize it anyway.

Upvotes: 0

Ateş G&#246;ral
Ateş G&#246;ral

Reputation: 140050

Opinionated answer, considering a way games handle server-client traffic. This is not the answer:

Rendering is a presentation concern. Your server, which is the single source of truth about the game state, should only care about changing and advertising the game state. 60fps rendering is not a server concern and therefore the server shouldn't be sending 60 updates per second for all moving objects (you might as well be better of just rendering the whole thing on the server and sending it over as a video stream).

The client should know about the game state and know how to render the changing game state at 60fps. The server should only send either state changes or events that change state to the client. In the latter case the client would know how to apply those events to change the state in tandem with the state known to the server.

For example, the server could be just sending the updated movement vectors (or even the acting forces) for each object and the client could be calculating the coordinates of each object based on their currently known movement vectors + the elapsed time.

Upvotes: 3

Lucas S.
Lucas S.

Reputation: 2401

Whenever a message is send over a network it not only contains the actual data you want to send but also a lot of additional data for routing, error prevention and other stuff. Since you're sending all your data in individual messages, you'll create these additional information for every single one of them.

So instead you should gather all data you need to send, save it into one object and send this one in a single message.

Upvotes: 0

Arillaxe
Arillaxe

Reputation: 85

Maybe its better not to send data every frame, but instead send it only on some particular events (etc. collisions,deaths,spawns)

Upvotes: 0

Related Questions