[MUD-Dev] UDP Revisited

Daniel.Harman at barclayscapital.com Daniel.Harman at barclayscapital.com
Fri Oct 12 16:22:21 CEST 2001


From: Brian Hook
> At 02:33 PM 10/10/01 +0100, Daniel Harman wrote:

>> The alternatives, which I believe Everquest may use, are to
>> either negotiate a port to communicate on through the log in
>> server, or to have a set of known ports with which one can
>> connect to the server, and to randomly pick one. Obviously the
>> former is more complicated as the negotiation probably takes
>> place using a standard tcp/ip connection with some form of
>> encryption, so you have to pass state between that and the UDP
>> part of the system.

> Why would the negotiation require TCP?  All the relevant state can
> be stored on the server and client, and UDP would be used to
> handle the negotiation.

So that I could leverage SSL for the negotiation. I've concluded
that its added complexity I don't want, at least in the initial cut.

> I would personally shy away from mixing and matching TCP and UDP.
> Adding a reliable transport layer on top of UDP isn't that
> difficult (anyone seriously working on this stuff should, at the
> very least, have a copy of Unix Network Programming by Stevens),
> and TCP performance is fairly slow and unpredictable.  From
> talking to others, one of the primary problems is that your TCP
> command stream can often be radically out of sync with your TCP
> one.  So if you try to sync your UDP stream with the occasional
> TCP packet, you can get really wacky results and hiccups.

I have 'Unix Network Programming' on my desk, and whilst a useful
basis for adding reliability to UDP, its not ideally suited to a
game. His example is based upon synchronous request-replies, with
both packets having to carry a timestamp. I plan to optimise by
sending bit field encoded acks piggy-backed on data packets, whilst
having the sender store the timestamp locally rather than sending it
(which I realise is largely what TCP/IP does, but that lacks the
non-guaranteed 'channel').

The other thing I'm doing is proposed in an article on gamasutra by
the developers of X-Wing vs Tie Fighter (The Internet Sucks: Or,
What I Learned Coding X-Wing vs. TIE Fighter, Peter Lincroft,
http://www.gamasutra.com/features/19990903/lincroft_01.htm ). Their
solution was to append the previous packets payload to each packet,
I won't really be able to measure how useful this is until I do some
live tests, but seeing as UDP packet loss is meant to be around 10%
it may help prevent resends. The only issue is that packets tend to
be dropped in batches, so it may not add that much in real terms.

>> Are there any reasons that I might want to not use a single port
>> for UDP with multiple clients other than the flooding aspect? It
>> just seems wasteful to instantiate a socket per client for a
>> connectionless protocol, although obviously from a defensive
>> point of view, its easier to stop servicing a port if someone
>> starts to flood it as it will only affect the flooder.

> The main advantage is that you can then associate port number with
> client, which is a nice easy correlation, e.g.:

>   clientIndex = incomingport - PORT_BASE;

> With a single port you'll have to hash the client's incoming
> address (via recvfrom()) into a table of clients.  This may or may
> not be a factor, but it does add some extra indirection:

>   clientIndex = hash( incomingAddress, NUM_PORTS );

The problem with assuming a socket is associated with a client has
to be that it makes spoofing even easier if you aren't checking the
header. I suppose if I have some form of authentication token or
encryption then that would solve that problem.

I've been doing some research into encryption too, and its apparent
that without hardware based encryption, and keys that are stored on
said hardware in a non-accessible location its verging on pointless
to even bother encrypting data. Whilst I know ShowEQ takes around 20
seconds to break a session key upon zoning using some form of
statistical analysis, if it were to actually read the clients RAM,
it wouldn't have to do much at all. I suppose a minimal level is
useful in that it should prevent intercepted packets from being
decoded with too much ease, but most of the problems in these games
seem to stem from clients that are complicit in the hack.

The engine I'm writing won't be as susceptible to a showeq type hack
anyway.  I intend to create 'data groups' with update rate dictated
by quad proximity in a quad tree of actors(which I'm additionally
hoping will facilitate actor collision detection), so frankly you
won't be getting info on something geographically a long way away
sent to you.

As you can imagine, I've been doing a lot of research here before
starting any code (completion port documentation is remarkable only
in its scarcity), and the most irritating thing is that I can find
no consensus on what the maximum safe size for a UDP packet
is. Every single article I have read has a different value, and
whilst I know the theoretical max (64k) its not too helpful as
that's considerably larger than any router is likely to tolerate.
If anyone knows the real value, I'd be grateful for their input.

Dan
_______________________________________________
MUD-Dev mailing list
MUD-Dev at kanga.nu
https://www.kanga.nu/lists/listinfo/mud-dev



More information about the mud-dev-archive mailing list