Suggests for a 2d networked game

Hi,
i’m doing a bomberman game.
I have already did a peer to peer version for 2 players.
Now i want to do an up-to 2 players version using a client server architecture.
What do you suggest me to use?
TCP or UDP?

Thank you

TCP for important data, UDP for not important data

So i should create a multicast socket for non important data and a thread with a tcp socket for every client?

It all depends, i think bomberman wont use that many data, so i guess you could send everything over tcp.
just try both and see what works out.

Ok, so i need a thread for each client, right??

yes always at least one, otherwise the neworking would not work right?
you need 1 listener thread to bind client requests.
And then give each client its own communication thread.

Thank you, i will try

And another question, i have positions to update, how can i pack my datas for sending??

Simplest way is sending the position and direction 0.5 to 2 times a second (try out what looks / works best).
for example: x, y, facing, iswalking
facing would be the direction the player is looking,

Both the server and client should be receiving this data about all players.

So in your client, you need to animate the player between the frames (10 steps between old / new frame for example), otherwise it will just telport to the new positions.
With frames i ment the dataframe you received about the player.

Using TCP and UDP increases UDP packet loss.

Not to mention if you use NIO, you don’t need multiple threads, you can have all of it in one thread… nice and scalable!

You mean asynchronous?

I had trouble trying to do that. I couln’t work out how to send packets back to the client without the client opening a ServerSocketChannel. If you know a way, please tell me. It’s something that’s bugged me for a while. If there isn’t, tell me too, so I can stop thinking about it.

Are we talking UDP here? or TCP?

Asynchronous server with TCP.

NIO is my specialty! I built a fun library that is a generic client/server API where you can pick a UDP or TCP backend, and then also pick whether you want it synchronous vs asynchronous (OIO vs NIO)… works pretty nicely.

I’ll start off explaining some basic concepts with NIO…

  • A Channel is either a connection to a client, or a server socket (see SelectableChannel).
  • A SelectionKey is something assigned to a channel, it has operations it’s ready to do, and operations it’s interested in doing.
  • A Selector has Channels registered to it, they register saying they are interested in performing some operation with the selector, and this registration process returns a SelectionKey used to tell or query the Selector.

A Selector is to be used in single thread, for the most part you shouldn’t do anything with it outside it’s thread.
It’s thread consists of something like this:


		try {
			// Enter the blockable area if the service has been interrupted.
			if (release.enter()) {
				try {
					// Select all ready events...
					selector.select();	
				}
				// If select throws an error (which will happen  its blocking
				// and this service has been requested to pause or stop).
				finally {
					release.exit();	
				}
			}
		} catch (IOException e) {
			// TODO
			e.printStackTrace();
		}

		// Only iterate the events if some were given (uninterrupted).
		Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
		
		// Iterate through each selected key in the set...
		while (keys.hasNext()) 
		{
			// Grab the next key and remove it from the set.
			SelectionKey key = keys.next();
			keys.remove();
			
			// If the key has been canceled, skip over it.
			if (!key.isValid()) {
				continue;
			}
			
			// The adapter that handles all events.
			Adapter adapter = (Adapter)key.attachment();
			
			// If the key is acceptable assume its attachment is a Server.
			if (key.isAcceptable()) {
				// Accept the connection, then continue processing keys.
				adapter.handleAccept();
			}
			else {
				// If the key is connectable, handle the connection.
				if (key.isConnectable()) {
					adapter.handleConnect();
				}
				// If the key is readable then handle reading, but only if
				// the key is still valid. The previous connect may have
				// canceled the key.
				if (key.isValid() && key.isReadable()) {
					adapter.handleRead();
				}
				// If the key is writable then handle writing, but only
				// if the key is still valid. The previous reading or
				// connecting may have canceled the key.
				if (key.isValid() && key.isWritable()) {
					adapter.handleWrite();
				}
			}
		}

pauses Hmmmm, this gets way more complicated and gets me very involved… maybe I should just send you my open source library and you can look through it and take what you want.

My problem was not NIO. I (mostly) understood that.

My problem was the asynchronous part.

I started typing out a response, but then deleted it all when I worked out the solution and ways to counter all the problems the solution could cause.

Thanks for the response though.

Eh, I really don’t like using Java’s NIO. I had a few problems with it, had trouble understanding it and getting it to work. Involving networking, I came from C++ which made a lot more sense to me. I don’t know, I think its a matter of preference, but I still have yet to make networking in java 100% work. I think the problem I had a few weeks ago was something to do with packet frequency. I sent a packet maybe 20 times per second, and it blocked out the chat packets, probably did something really bad there. :wink:

Sounds like you were using TCP+UDP

Ok so some totally terrible advice here, and some stuff that is just plain wrong. Don’t take it personally, but i get a feeling there is a lot of regurgitated “i heard that you do it this way”.

For any first cut, just use TCP. Only TCP. It does a bunch of hard stuff for you and has been tuned over the years to be pretty darn good. Only consider UDP if TCP is not working out. And then only if you understand the next points and you understand that its TCP that is causing the problems. Since your not networking with someone on the moon or mars, this seems very unlikely.

If you have never heard of flow control, or congestion collapse, then don’t use UDP.

If you don’t know what the 2 generals problem is then don’t use UDP.

There are other things you should know too before you do UDP. But mostly just don’t use it. TCP is not slower, its the same packets over the same network. In some cases it is still faster for reasons that its statefull and some routers and firewalls cache information about it, and ISPs typically prioritise TCP over UDP.

UDP packets can fragment and still incur reassembly cost on the IP stack anyway.

When you have enough packet loss to make TCP slow, UDP is also slow. You can’t change the fact that its still IP packets, and the packets get lost/reordered when you have congestion. TCP at least will deal with it properly (flow control).

TCP is far simpler since its doing everything for you and it just looks like a stream. Simple is good. Anything probably won’t work at all.

Network code is most games is total shit. Really. Just look at the forums for the different games about all the network issues. Right now a lot of games are moving back to TCP from UDP. Perhaps they finally didn’t get a game programmer for the network code and got someone who knows what they are talking about.

Your blocking is a thread issue most likely. . There is no way, unless you are on a 9600baud rate modem that 20 packets a second will do anything to a 10Mbit Ethernet connection or even a 14k connection. Doing both TCP and UDP is fine from a technical perspective. But there really is no point. Once congested, both TCP and UDP will be crap. Otherwise they both just work. Right now there are lots of TCP and UDP happening from your computer at the same time.

Note you can still do Asynchronous IO with just the streams that a TCP socket gives you. For a 2 player game there really is no need for the complications of NIO which is not really intended for such simple cases. Turn based listening could also work. Simple 2 threads with very little interaction could also work well.

I am not saying UDP is wrong. What i am saying is that its mostly used when TCP is better, and when its used its used Wrong. Very wrong. The overuse of UDP is based on the myth that its “faster”. This is not the case. If you don’t believe me. Test it.

TCP is slower only because it ensures packet ordering - which means if you do get packet loss then you have no chance of getting a later packet since the TCP stack is going to wait for the earlier ones. Nagles sorts out the TCP window/buffering issues.

UDP works better for data where your game/app is capable of carrying on even if it loses some packets. i.e. movement data - if I send positions:

Time = 1 - Position = W
Time = 2 - Position = X
Time = 3 - Position = Y
Time = 4 - Position = Z

And I lose a couple of packets so I receive:

Time = 1 - Position = W
Time = 4 - Position = Z

I can ignore the packet loss since I can get the later packet at time 4 and update to that position. TCP would delay you getting the packet at Time = 4 until it had managed to successfully resend 2 and 3. So if this was your networking model UDP would certainly be more tolerant to packet loss and faster than TCP. It’s a little more complicated when you want to do it in a real game because you’d like to be able to show smooth movement between point and you might now have the data - delta compression helps a bit here.

That said, knowing that your data channel is reliable lets you do some other optimisations on the client, so in certain cases TCP is way smarter way to go. For instance if you have no direct control over the actors in your game (think RTS with orders rather than shmup with direct control over your space ship) then you use TCP to great effect. Knowing the roughly consistent lag of a player and being able to reliably send an order to a server means you can loose-step things into place. (see HeadQuarter that one of the guys here wrote years ago). I wrote a blog on this ages ago - so long it’s dead on my site, but the power of way back gives me:

http://web.archive.org/web/20101228192125/http://www.cokeandcode.com/rtsnetworking

FWIW, I’m not saying “i heard you do it that way” - I’ve implemented systems using UDP, TCP and a combination of both for games and applications. Live video codecs is a great example for instance where old data isn’t very relevant once you’ve got a new key frame.

HTH

Cheers,

Kev