Authoritative game server allowing client action without strict acknowledgment - networking

I have a game I am working on that is client/server (fully authoritative). The game is not FPS or MMORPG. More like Clash of Clans where you can see other people's attacks, chat, manage your resources etc but no real-time players in the same battle/attack.
Nothing is saved on the client's phone (other than its uniqueID). So when it logs in, the server sends the player's current state/data.
Now, if the client wants to do something (move a unit, collect coins, start building something, etc)
The server will validate everything, of course, to prevent cheating.
However, I see 2 approaches:
1: No acknowledgment from the server
The client decides to do something, it is automatically applied on the client's side and it sends this information to the server.
The server validates the action. If it is legal, store the new information and do nothing.
No acknowledgment is sent to the client
The client was not waiting for acknowledgment either.
If the action was not valid (it means the client was cheating). The server does not save the state and close the connection.
2: Fully acknowledged
The client decides to do something, it sends this information to the server and waits (nothing happens on the client at the moment)
The server validates the action. If it is legal, store the new information.
Server sends the acknowledgment + the new state to the client.
The client then applies the new state.
If the action was not valid, it does not store the new information and sends an "invalid action" to the client. It can also decide to close the connection.
Option 1 reduces considerably the traffic between the client and server, plus the player does not feel "lags" when doing an action. And it does not remove the authoritative validation of the server.
Option 2 makes it more "legit" in the sense the client can never "see" an illegal move and the server always acknowledge something before the client can see it.
I assume most FPS will use something closer to option 2, but since it is not real-time I would assume option 1 would be ideal.
Any reason option 1 would cause an issue and I should go for option 2?

Related

Is an HTTP request 'atomic'

I understand an HTTP request will result in a response with a code and optional body.
If we call the originator of the request the 'client' and the recipient of the request the 'server'.
Then the sequence is
Client sends request
Server receives request
Server sends response
Client receive response
Is it possible for the Server to complete step 3 but step 4 does not happen (due to dropped connection, application error etc).
In other words: is it possible for the Server to 'believe' the client should have received the response, but the client for some reason has not?
Network is inherently unreliable. You can only know for sure a message arrived if the other party has acknowledged it, but you never know it did not.
Worse, with HTTP, the only acknowledge for the request is the answer and there is no acknowledge for the answer. That means:
The client knows the server has processed the request if it got the response. If it does not, it does not know whether the request was processed.
The server never knows whether the client got the answer.
The TCP stack does normally acknowledge the answer when closing the socket, but that information is not propagated to the application layer and it would not be useful there, because the stack can acknowledge receipt and then the application might not process the message anyway because it crashes (or power failed or something) and from perspective of the application it does not matter whether the reason was in the TCP stack or above it—either way the message was not processed.
The easiest way to handle this is to use idempotent operations. If the server gets the same request again, it has no side-effects and the response is the same. That way the client, if it times out waiting for the response, simply sends the request again and it will eventually (unless the connection was torn out never to be fixed again) get a response and the request will be completed.
If all else fails, you need to record the executed requests and eliminate the duplicates in the server. Because no network protocol can do that for you. It can eliminate many (as TCP does), but not all.
There is a specific section on that point on the HTTP RFC7230 6.6 Teardown (bold added):
(...)
If a server performs an immediate close of a TCP connection, there is
a significant risk that the client will not be able to read the last
HTTP response.
(...)
To avoid the TCP reset problem, servers typically close a connection
in stages. First, the server performs a half-close by closing only
the write side of the read/write connection. The server then
continues to read from the connection until it receives a
corresponding close by the client, or until the server is reasonably
certain that its own TCP stack has received the client's
acknowledgement of the packet(s) containing the server's last
response. Finally, the server fully closes the connection.
So yes, this response sent step is a quite complex stuff.
Check for example the Lingering close section on this Apache 2.4 document, or the complex FIN_WAIT/FIN_WAIT2 pages for Apache 2.0.
So, a good HTTP server should maintain the socket long enough to be reasonably certain that it's OK on the client side. But if you really need to acknowledge something in a web application, you should use a callback (image callback, ajax callback) asserting the response was fully loaded in the client browser (so another HTTP request). That means it's not atomic as you said, or at least not transactional like you could expect from a relational database. You need to add another request from the client, that maybe you'll never get (because the server had crash before receiving the acknowledgement), etc.

HTTP proxy server - need to handle dynamic client

I have developed serve-client model based on UDP. Client are connected to server on random basis. I mean number of clients alive at a time is not fixed.
Any new client can communicate any time. It means, there could be 1 live client or 100 clients or any number of clients.
Now in such model, I need to add HTTP requests. Browser could send request to server and then server will forward that to any of client based on some identification.
Is there any method or readymade server(like nginix or lighttpd), which I can use for this requirement.
My big worry is that, destination client are not fixed, they keep changing. Most of server (nginix or lighttd) have static entries for destination address.
I visualize your scenario as multiple sensors that connect to the servers when they have something to say, and then they send a request and wait for the answer.
I visualize you also want to somehow administer such modules so that you want to access to them via HTTP.
You could leave the new configuration items on the regular server so that upon any update connection the response would include (in a piggy-backed fashion) the changes to the node.
Or the server could mark somehow your interest in accessing a certain node, and then, when this connects, the server could notify the interested client. The sensor should pay attention to clients wanting to connect to them during a window time.
Certainly, more information would help us help you.

Server -> Many Clients: Simultaneous Events

Not sure what category this question falls into; perhaps general networking / design / algorithms.
For a project I am looking at having one server with multiple connected clients. After some time, when all clients have connected, the server should send a message to each client instructing them to take some action. I need to guarantee that each client will execute this action at exactly the same time. Theoretically, how can this be done? What are the practical complications I will come up against? My target platform is mobile.
One solution I can think of;
The server actively and continuously keep track of the round-trip latency for each client. Provided this latency doesn't change too fast over time, the server should be able to compensate for each client's lag and send messages to each such that they all start execution at roughly the same time. Is there a better way?
One not-really related question: Client side and server side events not firing simultaneously
It can easily be done.
You don't care about latency nor you need the same machine time at clients.
The key here is to create a precise appointment.
Since clients communicate to the server, and not vice versa (you didn't say anything about it though). I can give you the following solution:
When a client connects to the server, it should send their local time.
When the server thinks it's time for the event to be set. It should send an appointment event to each client, with their local time in it. Server can calculate this.
Then, each client knows when exactly they need to do something by setting a timer till the time for their appointment comes.
In theory yes you can but not in real life.
At least you should add some a validity time-slot. All actions should be in that predefined time-slot in order that action to be valid.
So basically "same moment" = "a predefined time slot".
A predefined time-slot can be any value that is close to same moment or real-time.

How to implement dual communication between server and client via http

I have a AJAX client which must receive messages from server. Some messages from server not like request-response type. For example, imaging game in which players can enter. Server must send to client info about player entering. But how can server send message to client via http without request from client?
Only decision that i can invent: client send request to server (getNewPlayerEnter request) with big timeout, server checks state of player set, if in set new players are, then server send info to client, if not server 'sleeps' on some time, and after 'sleeping' server checks players set again.
I think my desicion a little stupid(maybe not little). How implement it right?
p.s. sorry for my english
What you are referring to is "polling" where your client side code will make a request to the server every X seconds to check for updates.
It's an easy to implement solution, which is why you see it so often. However, a better solution is to use Comet.
In 2006, Alex Russell coined the term "Comet" to identify a technique whereby the client makes and HTTP request to the server and the server keeps that connection open indefinitely. With this open connection, the server can then push updates to the client in the response when there are updates.
When the response is received, the client immediately opens a new long-lived HTTP connection.
I encourage you to do a search for "Comet" and whatever server-side language you are using to find a framework that will get you started.
Comet Daily has some really great demos, from chat applications to games, that use Comet. If you have a tool like Firebug or Chrome Debugger, you can observe the response/request cycle of these real-time applications.
http://cometdaily.com/2009/10/23/concrete-comet-examples/
The way this typically would be done is for the client to ping the server on a regular interval (say, every 10-seconds). If there has been a change on the server, the change is sent back to the client. If there has been no change, either a blank response is sent, or some sort of "no-change" code that you specify.

What TCP protocols are usable for client to client communication?

Manytimes clients ask for features like instant messaging (IM) and other client-to-client (P2P) communication for their web apps. Typically how is this done in normal web browsers? For example I've seen demos of Google Wave (and Gmail) that are able to IM from a regular browser. Is this via HTTP? Or does XmlHttpRequest (AJAX) provide the necessary backend for such communication?
More than anything I wonder how can a server "wake up" the remote client, lets say for sending an IM? Or does the client have to keep "polling" the message server for new IMs?
Typically the browser will poll the server for new messages. One approach that is often done to make this more efficient is the 'long poll' (see also this link) - the server responds immediately if it has anything; otherwise, it waits, keeping the connection open for a while. If a message comes in, it immediately wakes up and sends it, otherwise it comes back with a 'nope, check back' after a few tens of seconds. The client them immediately redials to go back into the long-polling state.

Resources