TCP or UDP for my game?

Hi

i’ve read almost all TCP vs UDP thread, but i still have some question.

my game will be very x-wing vs tie-fighter like, almost a clone.

I’ve had some version running, fine in LAN, but unplayable on the internet.

My physic is DETERMINISTIC: so I can just send the input of the player to host, and from the host “collect” the actions and send them back to all clients.

also on client side i use 2 world: one is sinc with host world, the other is ainc and only use the action from client’s side, and generally is in the future respect sinc world of “ping/2” ms.

Probably client will send very small packet every time an input is readed, while the server will elaborate this action “pool” at 30 or 40 FPS.

now imagine a 40FPS action update cycle (25ms).

A server collect all the action arrived during the current FPS, and execute them in the next FPS, then send them back to all client (well, sending them back can be done immediately, but then there will be too much overhead)

client A’s ping with host is 100ms
client B’s ping with host is 120ms

client A shot, the action arrive with 50ms of lag, worst case add 25ms for action to be executed, and send it back. because of asinc world, client A see it’s shot after 50ms from send, and it will be corrected to 75ms after 125ms. I think that 50ms (or better half ping) from clicking a button and ship reaction are too much.
client B see the shot after 25+60ms, 85ms! this is too much in a shooter game!

ok, maybe 100ms is not a good ping, but many game still playable. Ok thanks to asinc world the experienced lag is “ping/2+25ms”(worst case, with a “warp” of 25ms) on your ship, but you will still experience “your ping/2+25ms”(worst case) lag for other’s ship.

As you can see I need guaranteed delivery(at least from server to client side), but I don’t care about the order. client will send small packet very fast, and server “big” packet every 25ms.

TCP.

If you need deterministic physics, then you basically have to ensure that all packages get there one way or another. TCP does this for you. Lots of people will literally scream at you that TCP sucks balls and that you should always use UDP. This is completely wrong in this case, because if you were to use UDP you’d have create a TCP clone on top of it to handle resending and confirmation, e.t.c. Do you think you’re better at writing network protocols than the people who came up with TCP? Use TCP.

TCP, unless it’s not important,

If SCTP were actually usable, it’d be perfect. Since using it over the internet is a pipe dream, use the next best thing: TCP. Be sure to turn off the Nagle algorithm (Socket.setNoDelay(true)) for low latency. You’ll also want to look into the tunables in Socket.setPerformancePreferences – just don’t expect dramatic results from them.

Kill Nagle’s algorithm the first thing you do. Having it enabled sneakily enough works fine during local testing (as it isn’t used), but as soon as you have two computers connecting to each other you’ll see ping jumping between 0 and 300 over LAN.

OMG I didn’t know about this, that’s amazing. I need to try that.

Disabling Nagle’s algorithm might actually hurt. As every .write(…) will result in a distinct TCP packet.

I usually leave Nagle’s algorithm on, and .flush() the OutputStream when I’m done with the message. That way I can make the OS pick the most efficient TCP packet sizes, while I’m generating the data, without the fear of doing a write(byte[]) that is too small (increasing overhead) or slightly too big (in which case a second, tiny TCP packet will be created, which is even worse).

IMHO, Nagle’s algorithm should only be disabled if you’re either a networking expert, or using NIO, which doesn’t have a flushing mechanism.

Maybe you’d assemble the entire byte[] you were going to send and only issue a single write() though.

Cas :slight_smile:

Reading the original post, I think the author isn’t.

[quote]My physic is DETERMINISTIC
[/quote]
Independent of the networking aspect to your question, are you absolutely sure about this?

One shouldn’t disable Nagle if they want maximum throughput on streams, no, but unless you want built-in delay on every packet smaller than the MTU, you’ll want it on. Flush is a userspace operation, and does not actually guarantee the TCP layer will immediately deliver your packet.

Obviously, don’t take on faith what you can and should measure. If you’re close to saturating the link for example, disabling Nagle will only make things worse.

Gotta admit I don’t, but it was a pretty long time since I did networking using byte[]s. I’ve only been using ByteBuffers recently, but not enough to actually be bothering about performance. Disabling Nagle’s and using either a custom buffer or a BufferedOutputStream should be enough to accomplish that, right? Just flushing it (which actually should flush it with a single write()) every frame should work fine.

Does anyone know if Nagle’s algorithm is used in NIO?

You won’t be close to saturating the link with a game unless you’re Doing Something Wrong. You should be able to stay well under 10kb/sec upload, and if that saturates your link… Well, I guess the delay that comes with such a connection doesn’t make it fit for gaming in the first place. If you do some simple buffering yourself you should be able to get something in between Nagle’s and nothing at all. I’d say that’s the best compromise.

I’m serializing object on java NIO, and this object is a linked list of actions… so every write should be be a flush. I’m also truncating the array on the size of MTU-100, and putting exceeding action in another array, but maybe this should be done by NIO.

Independent of the networking aspect to your question, are you absolutely sure about this?
[/quote]
yes! and i’m really happy about this. Physic is just 2D (jbox2D), but with some trick is full deterministic on windows (32 and 64bit), linux (32 and 64 bit), also windows machine was intel, linux was AMD plus a 32bit linux intel(eeepc!). I have an old mac to test on, but actually never “played” with him (I’ve to reinstall OS and so on…) more info on: http://box2d.org/forum/viewtopic.php?f=9&t=7074&start=10

stream saturation can be easily archived in the host, if there are too many player.

I couldn’t help but notice the stickied topic right above this one. Odds are it visited the same topics this one did. Whatever you decide to optimize or tune, just make sure you make one change at a time and make sure to measure it, on the hardware and software you expect to be using in the real world (or at least as close as you can get).

I’m building a test engine for determinism, with a fake network layer.
I’ll write news on jbox2d page, but i think I’ll use TCP with noDelay(Nagle turned off), and let you know when i’ll make it work.