Crossfire Mailing List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A few thoughts on client/server in multi-player games



  From:  quinet@montefiore.ulg.ac.be (Raphael Quinet)
  Date:  Mon, 11 Apr 94 01:56:43 +0200

  
  > I find Carl Edman's views very convincing. A two-digit number can be
  > transferred in less space than a 32-bit binary number. You don't have
  > to name the protocol commands "transfer_this_list_of_images_please",
  > "TMI" will do :-)
  > 
  Sure, but what about command #7, where the "7" is stored in a single char?
  
  We don't need to use 32-bit numbers.  We could use single chars when the
  value is small (int8), and two chars for greater values (int16), using
  32-bit ints only for huge values.
  
  I already hear you say: "but you will need to translate all numbers, so why
  don't you use ASCII instead?".  Simple: binary data consumes fewer bytes
  than ASCII data, and casting a char to an int is much faster than using
  atoi/itoa/sprintf/sscanf, etc...
  
i've been involved in the development of a half-dozen or so client-server
protocols (X font server, LBX, a number of NCD-proprietary), and i'll
offer a few observations.

- binary vs ascii.  either can work fine -- choose the one that best
    solves the problem.  byte swapping and data size is a red herring.
    byte swapping is easily solved by communicating the byte order of
    the client or server at startup time, and having one of them swap
    stuff as required.  data size is worked around by defining things in
    terms of bytes or bits -- don't use 'long' or 'int'.  check out the
    X protocol's usage of BYTE, CARD16, CARD32 etc.  one thing you may
    want to do is force word padding, since a lot of archs get annoyed
    (or slow down) if you try to look at (say) a CARD32 that doesn't
    start on a word boundary.  floating point is uglier, but its been
    handled in a number of X extensions -- take a look at XIE or PEX.

    i haven't thought enough about what crossfire needs to know which is
    better.  ascii can be much easier to debug when you're developing
    the protocol, and if the messages are simple enough, its probably
    compact enough.  but remember that decoding the ascii stream will
    take more effort than decoding a binary stream.  a bunch of strcmp()s
    are a lot more expansive than a big switch statement that looks at
    the first message byte as an opcode.

    a binary protocol is also easier to make more uniform.  you can
    lay out the packets to be a similar as possible, which speeds up
    decoding time.

    either form can be extended with similar ease, though you should
    specify the extension methods up front.

- avoid the ftp thing completely, and build it into the protocol.
    when the server tells the client to display some new object, it sends
    the object description down to it, along with a tag it will use for
    any future references.  having the server transport the data should be
    at least as fast as ftp, and attaching the tag to the packet is a safe
    way to keep things in sync.  if the client gets too full of objects,
    or decides one is 'old', it simply tells the server.  the server
    can also obsolete objects this way, if that becomes interesting
    (maybe you want to change the maps out from under a running server,
    or change a monster bitmap...)

    we use this concept a lot in LBX and its a major win in reducing
    bandwidth.  (you may want to borrow some of the LBX code...)

    building in the transport avoids security issues -- if you let the
    client connect, then you must consider it secure enough to transport
    files.  just make sure the client can't ask for anything the server
    doesn't want it to have.

- make sure your connection protocol agrees on all possible options.
   if the client can't handle sounds, don't waste the time sending
   anything to do with sound.  if the client is monochrome, make sure it
   gets bitmaps, not pixmaps, etc

as for the rationale for client-server, i don't know if its needed or
not, but i agree that it should be possible to make a non-X crossfire
client.  it shouldn't be too hard to make a Mac or Windows client,
and if you want to make the game more popular, that's certainly a good
goal.  and this means data (maps, images, sounds) must be in some
canonical format.  ascii may be too general for maps (and the current
crossfire map format should at least be compressed before putting it on
the wire).

one other thing i haven't seen discussed is the type of connection you
want to use.  since its multi-player, you have to be able to deal with
different connection speeds to the same server.  if one of the players
is running at 9600 baud, and the others on the local ethernet, someone is
likely to be unhappy.  if you use TCP, it'll run at 9600 baud for everyone
unless you start tossing frames. if you use UDP,  you'll have an easier
time keeping things in sync, but if the wrong packet gets tossed by the
OS, a player could be very unhappy.  you may want to check out xpilot.
it uses UDP, but losing a packet is less catastrophic, and all the large
data transfer is up-front.


and as for using gprof to tune, you're not likely to get terrinbly far
that way.  i'd guess it shows lots of time in process_events() for the
normal reason -- its primarily event driven, so it spends all its time
waiting for a new event to come in or a new frame to occur.

Dave