<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40581 >

> [EMAIL PROTECTED] - Tue Nov 25 05:40:06 2008]:
> I thought the request_id was intended to associate a packet sent to
> the client with the particular request that the client had sent to the
> server.
> [...] 
> Now at what point does the client state change?  I don't know the
> current situation actually but there's two ways to do it.
> 1. [...]
> 2.  When the server approves the buy and sends the city info back to
> the client, the client only then updates the purchase.  This is, of
> course, safer and more reliable.  But if there's a high-lag connection
> it'll be a lot less user-friendly - potentially cripplingly so.  The
> saferness comes into play when a purchase fails at the server end;
> with case 1 you'd have the client incorrectly update the city info
> itself then receive the new (original) info back again and revert.
> Such situations would be rare however; they can happen with some
> rulesets or server mods maybe but are most likely to happen if the
> player tries to buy right as the turn ends and the server doesn't
> handle the request til the following turn.

In my own experience the situations where something would
change between the time the client sends the packet and
the server receives the packet happen quite frequently,
especially during times when there is a lot of fighting
between players with a substantial difference in ping.
Cities get taken or destroyed and units get moved, killed,
etc. before the information fully propagates.

So my opinion is that method 2 is safer and more robust for
the multiplayer case. For single player it does not matter
so much which method is used since lag is almost always
not an issue (e.g. there is no timeout or the server is

It would perhaps help if the gui reflected the client-server
nature of the communication. This could be done by having
the gui show a "pending" state for an operation when the
client sends a packet, and only when it receives a response
from the server update the gui to show whether the operation
succeeded or failed (of course it would only update its copy
of the data structures when the operation succeeds).

Incidentally I may have "reimplemented" the request_id system
in some of the editor code where I have made use of packet
"tags"... :/

> Okay having given that example, I still don't see a use there for the
> request_id.  So how is it used again?  Just as an outdated variant of
> the freeze/thaw mechanism?

That seems to be the case in most of the code I have examined.
The agents/cma would appear to make use of it as well, as a
mechanism to associate server responses to agent requests.
(The cleanup and update of the agent system, perhaps to lua,
is another RFC entirely...)

I did think of a perhaps cleaner design that would allow the
best possible implementation of all of the previously mentioned
behaviours, and more. My idea would be to extend the packet
header so that in addition to the type and size fields it would
also contain:

int request_id; /* A.k.a. tag. */
int sequence_number;
int sequence_total;

The first field would function like the current request_ids/
tags, allowing the sender (i.e. both client and server) to
associate a response with a previously sent request. In my
opinion it makes more sense to have this in the packet header
(i.e. not subject to delta compression obviously), than as a
field in the connection struct (where it is, in my opinion,
ugly in the same manner that a global variable is).

This would mean that packet handler functions that want to make
use of the fields inside the header would have to take the
packet pointer as an argument (rather than just the individual
packet fields), or something like that (e.g. a pointer to the

The sequence fields inform the receiver about whether to expect
that this packet is part of a burst of similar packets. This
way cases where a mass of packets are sent can be optimized by
the receiving end, e.g. the server handling a bunch of unit
moves at once, or the client waiting until all information is
received before doing a gui update.

As a further example, this could be used to implement a progress
bar in the client gui for receiving and loading the ruleset data
when connecting to a server, or when handling the mass of info
packets when becoming a player or observer.


Freeciv-dev mailing list

Reply via email to