In my experience, UDP has such low overhead that one thread can handle thousands of packets per second per socket.
It’s one of the reasons that UDP is so loved in the game industry.
Mostly TCP is used only by turn-based games and MMOs, where the rubber-banding latency issues are usually unimportant (TCP can lag for minutes at times!).
There are also a number of realtime low-latency games that use TCP and should be using UDP instead
I still regard the QuakeWorld Server design as good practice for realtime games… It allocates only one socket (which makes it easy to portforward), and simply services incoming packets as they come
in (using select to sleep between packets), when a client input packet comes in, it updates the game world (if enough time has passed to justify it, like 20ms or so), and replies with a new game state
for that client (detailing the game objects near the client, and any events that occurred since the last packet, such as chat messages).
UDP vs TCP, point by point:
GREAT: Low latency despite packet loss - TCP has “rubberbanding” lag when packet loss occurs because it must repeatedly try to send the same packet again (even if it’s now rather out of date), and
won’t deliver the packets to the app until the preceding packets are delivered, in order.
GOOD: Exact control over bandwidth - TCP has very erratic bandwidth utilization as its only goal is to deliver the stream as fast as possible, UDP delivers distinct packets as you see fit.
GOOD: Non-blocking API - simply enabling non-blocking I/O on the socket is enough to avoid all need for threading of the network layer.
BAD: Out of order delivery - UDP packets are not guaranteed to arrive in order, in general games address this by numbering all the packets and dropping ones that are older than previously received ones.
BAD: Duplicate packets - UDP packets are not guaranteed to arrive only once, they may arrive multiple times (went the routers sent them on multiple paths due to uncertainty), again this is addressed
by checking packet numbers and dropping ones that are not new.
BAD: Packet loss - UDP packets are not guaranteed to arrive (ever), in general games address this by checking for gaps in the packet numbers and acknowledging receipt of every packet number to the
peer in the next packet (may be more than one packet recieved per packet sent, depending on your send/receive frequencies), if a peer acknowledges a given packet number then you can safely use that
packet for compression or other purposes (for instance repeating a reliable message in a future packet if a gap in packet numbers was detected).
BAD: Maximum packet size - UDP packets can not be fragmented, and thus can only be up to 1400-1500 bytes safely on the internet (some routers may pass 9000 bytes, but I wouldn’t bet on it).
So on the whole, UDP is vastly superior for realtime games, but a lot more work.
Some games use both a UDP socket (for rapidly updating data) and a TCP socket (for important communication), and send different kinds of data on each connection, but this means blocking I/O hassles on
the TCP sockets, and can still experience the rubberbanding lag behavior on the TCP-carried data.
P.S. UDP fragmenting actually exists but is deeply flawed, so internet routers don’t pass UDP fragments.On 10/22/2011 07:31 PM, Patrick Baggett wrote:
If you’re using UDP, then one thread to check the all of sockets is probably fine. Basically, that thread reads data, validates it, and then packages it in a way that the rest of the game engine can
understand it (i.e. does little to no processing on it all). This has two major points. The first is that you don’t spend much time trying to process network traffic on the thread that is responsible
for fetching it, so the latency is lower. Two, you separate the network details from the game engine stuff. That way, you can have a client who is local that mimics the network protocol by packaging
stuff like keyboard/mouse input into a game-undestandable format. Really though, that is a discussion more about software architecture and interfaces.
For the purposes of < 16 clients, 1 thread that handles network I/O is probably fine. When you call [non-blocking] recv(), the data isn’t being read from the network card – it is already in memory in
the OS kernel, so it isn’t like you are handling the delay of network transmissions when you call it. As far as burning through CPU, even a simple hack like Sleep(1), however unclean, would stop you
from absolutely hogging a single CPU core. More appropriately, you can use as Alex mentioned a select() / event notification system with a timeout. Even waiting a few msec for traffic will keep the
CPU utilization near 0.
On Sat, Oct 22, 2011 at 9:14 PM, Alex Barry <alex.barry at gmail.com <mailto:alex.barry at gmail.com>> wrote:
Hi Yuri,
I think I can answer that. When your running a server, it is almost impossible, especially in a game situation, to run on a single thread. This is because some socket functions are blocking (the
program waits until the operation is complete), or generally slow. Blocking can be resolved with using select (i believe SDL_net uses socket sets which in the background use this call). Mostly,
if your server is handling multiple clients and each need near-real time responses, it is ideal for each client to have its own thread so the server can process each client in isolation and fairly
quickly.
If your server only gives data to the client after the client asks for it, having each client thread have blocking sockets means your server isn't burning through cpu time/power, and each blocking
call doesn't affect other clients. In a game situation, clients don't necessarily need their own blocking thread, but it is nice to handle client connections in a separate thread for speed, and a
certain sense of sterileness.
I hope that explains a little bit of it :)
-Alex
On Sat, Oct 22, 2011 at 9:08 PM, Yuri David Santos <yuri at aleva.com.br <mailto:yuri at aleva.com.br>> wrote:
Hi Bruce,
I read some parts of your code and it has the answer for some of my questions. About TuxMath, why do you use the server in a separate thread or process? To keep listening to client messages?
Could I do the server message handling and game updates in the same thread?
I would like to see your game working, it is on the ubuntu repository?
Thank you very much!! :D
2011/10/22 David Bruce <davidstuartbruce at gmail.com <mailto:davidstuartbruce at gmail.com>>
Hi Yuri,
> Thank you two. David, I would like to see your code, but how do I do that?
> There are many directories... I have no idea what file I must to download.
> Sorry for the ignorance (and my bad english).
https://alioth.debian.org/frs/download.php/3571/tuxmath_w_fonts-2.0.3.tar.gz
If you want to actually build tuxmath, you also need our common library:
https://alioth.debian.org/frs/download.php/3540/t4k_common-0.1.1.tar.gz
Again, I'm not an expert programmer, so I can't guarantee my code is
optimal, but it does work. I figured it out by:
1. Reading Beej's sockets programming tutorial (google for it)
2. Googling for SDL_net tutorials.
3. Asking on this list.
Basically, I used TCP for the actual game connection as tuxmath has
very minimal network performance needs. You may find folks saying
"Use UDP for games because it is faster" but my type of game didn't
need it.
The client finds the server on the LAN by making a UDP broadcast.
When the server gets a packet from a client, it then knows the
client's IP address and sends a packet back saying "server at IP
xxx.xxx.xxx.xxx". There can be more than one server on the network.
The client program then can pick which server to connect to with TCP.
I would bet that there are many other open source games that do the
same thing and were written by more knowledgable programmers than me.
In particular, I can't promise that my code doesn't have security
holes in case your program is going to be exposed to the internet at
large. (Note that the broadcast autodetection routine wouldn't work
over the internet anyway, although the connections themselves would
work).
Hope that helps,
--
David Bruce
For all your software needs, visit The Apt Store:
deb http://ftp.us.debian.org/debian stable main
_______________________________________________
SDL mailing list
SDL at lists.libsdl.org <mailto:SDL at lists.libsdl.org>
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
--
Yuri David Santos
Aleva - Solu??es em Software
www.aleva.com.br <http://www.aleva.com.br>
_______________________________________________
SDL mailing list
SDL at lists.libsdl.org <mailto:SDL at lists.libsdl.org>
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
_______________________________________________
SDL mailing list
SDL at lists.libsdl.org <mailto:SDL at lists.libsdl.org>
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
–
LordHavoc
Author of DarkPlaces Quake1 engine - http://icculus.org/twilight/darkplaces
Co-designer of Nexuiz - http://alientrap.org/nexuiz
"War does not prove who is right, it proves who is left." - Unknown
"Any sufficiently advanced technology is indistinguishable from a rigged demo." - James Klass
"A game is a series of interesting choices." - Sid Meier