I've been making a simple socket.io program where the players can move around in an environment, with the client sending the server events.
However, it seems that the client can use the console to falsify data and send it to the server (by using socket.emit()).
Is there a way to combat that, so that the server only accepts "real" data, or to prevent the client from sending false data?
Your server should always hold the state of the application, and have a list of all possible actions for each state.
For example, if your character can move on a map, the server should always keep the coordinate of the player. Let's say the player is at coordinate (x, y). The server will only allow messages that move the player to (x+1, y+1), (x-1, y+1), (x+1, y-1) or (x-1, y-1). Any other message should be discarded.
If it receives a message saying the player wants to move to (x+500, y+500), it should ignore it and potentially mark the player as a cheater and disconnect it.
Related
Example:
Schedule a notification for 15 minutes and save the user's location.
If the user leaves radius, the notification will not be sent.
Would it be possible to do this using onesignal or just with cordovaLocalNotification?
var notificationObj = {
contents: {
en: "asdasdasd"
},
include_player_ids: [playerId],
send_after: "2017-02-15 20:42:00 GMT-0200",
}
window.plugins.OneSignal.postNotification(notificationObj,
function(successResponse) {
console.log("Notification Post Success:", successResponse);
},
function (failedResponse) {
console.log("Notification Post Failed: ", failedResponse);
alert("Notification Post Failed:\n" + JSON.stringify(failedResponse));
}
)
})
Before that I would save the current location and at the time of sending I would compare if the location is within the 1km radius. If yes, I would send it if not, I would not send
There are two types of notifications: local notifications and push notifications.
Local notifications work like an alert (i.e. I want to be awaked at 9AM) and they can be saved and launched locally, without any internet connection, at the specified time. For this kind of notifications, you can use the Local Notifications plugin.
The second case, Push Notifications, are sent (basically...) from your server to the user app via internet suitably a kind of notification rules set server side.
So, for you specific case, if I got your needs, you can:
get your actual location and timing, send all these data to your server
save (server side) these data and set a timing (15 mins) to send a push notification
after 15 mins, without info from the client app, send the push notitication.
If the user leave the circle radius, send a message to your server, telling "I'm out of the circle, don't send me the push notification". You can decide, server side, to stop the further notification sending.
So, for your case, I would just use Push Notifications.
Little drawback: if the user looses connection and leaves the circle, the client message would not be sent to the server and the server would not be alerted about that, so it'll send the notification to the user. Anyway you can manage, client side, this case to avoid it.
Edit: you can also manage everything using Local Notifications as alerts and don't use Push Notifications at all, as you wish. I would not use both systems.
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?
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.
Maybe its better not to send data every frame, but instead send it only on some particular events (etc. collisions,deaths,spawns)
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.
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:
Player with socket id player1 sends his data (let's say coordinates {x:5, y:5})
Server receives the data and saves it in an object containing all players' data:
{
"player1": {x:5, y:5},
"player2": ...
...
}
Server sends that object to player1.
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:
The sending player gets the other players' data immediately, meaning that he doesn't wait for the server's 60 times-per-second update.
If the player's browser crashes, he no longer sends data and therefore no longer receives it since he can't visualize it anyway.
Short question:
Can latency, when a client is sending packets to the server suddenly change a lot?
Long question(the problem I've got):
I'm making a html game using websockets and currently working on client side input prediction, I'm using the same code for client and for server to check for collisions, calculate new player positions, 30times/second. This is how I update player movement on both server and client side:
if(controls.pressingRight === true)
{
if(controls.dx < settings.MAX_X_SPEED)
{
controls.dx += settings.DELTA_X_SPEED;
}
else
{
controls.dx = settings.MAX_X_SPEED;
}
}
if(*noCollisions*)
{
game.me.x += controls.dx;
}
This way the player movement is kind of smooth. When a user press and holds down "D" keyboard button conrols.pressingRight value is changed to true, and it is true until player releases the "D" button. The reason I wrote my code is because I'm not sure if the problem is in my code or it has something to do with the change of latency. For example I click D button and quickly release it and my player on my client canvas moves like ~7pixels BUT on my server side player moves like 20pixels or more to the side(though sometimes both client and server side moves the same amount of pixels). I'm guessing that the problem is because when I press button down to move the player the latency might be low, let's say 20, but when I release the ping might be like 200 which means the packet was delivered later than it should've and because of that server still had my value of "pressingRight" as true. Am I missing on something?
Can latency, when a client is sending packets to the server suddenly change a lot?
Yes, absolutely. Connectivity changes occur all the time. This is especially true in mobile devices with antennas moving around quite a bit, causing momentarily loss in connectivity.
I'm making a html game using websockets and currently working on client side input prediction, I'm using the same code for client and for server to check for collisions, calculate new player positions, 30times/second.
...
When a user press and holds down "D" keyboard button conrols.pressingRight value is changed to true, and it is true until player releases the "D" button.
This is definitely one way, but if you go this route the server should be your source of truth as to the state of things. The client can move to where it think it moved, and then the server can update positions, bouncing the client back to the standard server-known version of events. In the optimal situation, the client won't move by much. However, lag happens, and sometimes that client is going to snap back to a location much further away.
There is no perfect solution to this problem when the game requires such interactivity. However, there are many ways to address it. See also: http://gafferongames.com/networking-for-game-programmers/what-every-programmer-needs-to-know-about-game-networking/
I am using the Poco C++ libraries to setup a websocket server, which clients can connect to and stream some data to their webinterface. So I have a loop which continuously sends data and I also want to listen if the clients closes the connection by using the receiveFrame() function, for the rest, the client is totally passive and doesn't send any data or whatsoever. The problem is that receiveFrame() blocks the connection, which is not what I want. I basically want to check if the client has not yet called the close() javascript function and stop streaming data if it has. I tried using
ws.setBlocking(false);
But now receiveFrame throws an exception every time it is called. I also tried removing receiveFrame entirely, which works if the connection is terminated by closing the browser but if the client calls the function close(), the server still tries to send data to the client. So how can I pull this off? Is there somehow a way to check if there are client frames to be received and if not to just continue?
You can repeatedly call Socket::select() (with timeout) in a separate thread; when you detect a readable socket, call receiveFrame(). In spite of the misleading name, Socket::select() call wraps epoll() or poll() on platforms where those are available.
You can also implement this in somewhat more complicated but perhaps a more elegant fashion with Poco::NotificationQueues, posting a notification every time when a socket is readable and reading data in the handler.
setBlocking() does not do what you would expect it to. Here's a little info on it:
http://www.scottklement.com/rpg/socktut/nonblocking.html
What you probably want to do is use setReceiveTimeout() on your socket to control how long it will wait for before giving you back control. Then test your response and loop everything if needed. The Poco docs have more info on how to use that part of the API. Just look up WebSockets.
I've got a working Websockets example, where clients receive messages from the server.
I'm not sure how I should send old messages to clients when they connect.
Example:
Each client supplies their name when they connect
The server responds with "[name] just connected" (to all clients)
Any new clients would NOT get these messages
I'm wondering if there's any way clients can receive old messages (either all of them, or messages in the last 5 minutes would be acceptable).
I suspect I may have to capture this information myself, store it somewhere (like a database) and send the messages to new clients myself. Is that right, or am I missing something?
If anyone has pseudo code, or a link to an example of how others have implemented this, that would be handy.
You could do something like this:
Each message should have an id -> muid (Message Unique ID)
Each time a client send s a message, it gets an ACK from the server along with the muid for the sent message.
Each time a new message is received in the server side, a muid is assigned, sent with the ACK and also sent with the message to every connected user. This way the view will be able to present, for every user, the same sequence at some point in the time.
Each time a new user connects it sends the last muid it has received so the server knows where this user stopped receiving messages. The server could then send as many old messages as you want, depending on the kind of storage you implement:
Full history: I would recommend a database storage with proper indexing
Last N messages: Depending on the size of N you could simply store the last N messages in a fixed size Array and send them, all or the needed chunk, on each reconnection. Keep in mind that this will consume memory so, storing last 1024 messages for 1024 different chats would eat quite a bit of memory, specially if messages are of unlimited size.
Hope it helps
You will have to capture it by your own and store it on server... once user connects you will have to name that data to all connected clients and the messages which you have stored back to the user who has connected. So, you will have to code to broadcast the data to users
By the way what are you using server side? (Node, Erlang , etc)
You can check following link if you are using node.js
http://martinsikora.com/nodejs-and-websocket-simple-chat-tutorial