1
\$\begingroup\$

I am working on making a 2D platforming game that will have multiplayer functionality. Over the last few days, I have done a lot of reading regarding how to deal with the networking, and believe that I am on the way to implementing some of the concepts I have read about.

I have decided to go with an Authoritative server/client model, where multiple clients will send actions made by the user to the server, client will predict the players next steps before comparing against the Authoritative reply from the server, etc. This seems to have been suggested in numerous corners of the web regarding games networking, and seems reasonable.

Before jumping straight into trying to get snapshots sent from the server, I wanted to make sure that I had an idea of some of the technical nuances of a language, as conceptual knowledge can only get me so far. I have set up a simple Echo Server that has worked rather well for a single client, but now my next step is to have multiple clients connected to the server at a single moment, and have each message that is sent from a client echoed to all clients connected to the server.

I feel that the answer might be language dependent, so I will mention now that currently I am using Java for the networking (a little bit of preliminary testing may suggest that Java has significant overhead in its network implementation, so I am open to change upon suggestion). I am using UDP for speed sake (and this seems to be what is predominantly suggested).

My question is with the server, should I be keeping each DatagramSocket that represents a connected client open and send DatagramPackets directly out without ever closing them (until the program terminates, client disconnects, etc.), and have them stored in some form of Collection, or should I close them after each message is sent and create a new outgoing socket whenever I need to send a packet? There are obvious performance disadvantages of creating a socket whenever I need to send a message, but is there some fundamental reason that I have not come across that suggests leaving sockets open is not a good idea?

\$\endgroup\$
2
\$\begingroup\$

You should be able to use java without any performance problems, the technology went way past that. Although services that work with massive number of clients still use c++.

As for your choice of sockets, it's not a matter of performance, as people usually think, it's about what are you going to use them for.
On game servers you don't care if messages are out of order or got lost, you just want updates going as fast as possible. Lost messages can be ignored and if you get messages in order: 1 2 4 3, you just ignore message 3, because you already got the newer update (4). In this case you use UDP sockets (which is actually a simple wrapper over internet protocol (IP)).
But on the web you want all the content to arrive in order. You don't want the footer of your .html page to be processed before the header, or to lose part of the .html page with the closing tags, because it would screw up everything, neither do you want to get second frame of your youtube video before the first one. So here you use TCP sockets that will rearrange the packets as they come to be in order and resend the request for parts that were lost (this is also a wrapper over IP, but it has a lot of optimization and features developed over past 30 years).

Many applications use both TCP and UDP on the same port, which is pretty handy, but if you're making a game server and want to make sure the "attack" command gets to the server when client on the mouse you would be better off implementing it using the same UDP socket you use for updates.

As for how to implement this, my practice is to have a single socket on the server that would receive all the requests and send all the responses (don't process the requests in the same thread that receives them). And identify the clients by their IPEndPoint (plus whatever type of token you use for security, if any). Just remember the IPEndPoint of the clients, so you know where to send the response, or in case you need to send them something asynchronously.

Making a new sockets for each client is something you do with TCP, when you use TCPListener. But UDP sockets aren't bound to any client, so making a new sockets for each client is useless, it just means you'll have to bind a lot of ports (and setup port forwarding for all ports to your computer if you're behind a router).

\$\endgroup\$
  • \$\begingroup\$ Right, that sounds good. You mentioned having TCP in your 3rd paragraph in regards to sending an attack command from the client to the server an an example. Is TCP something I should be implementing for these sorts of things? I would have thought the hand shaking and ACK's would be a major issue in regards to speed, but if this is the done thing, then I will just have to do some testing. Thanks for the answer, it looks like it is what I am looking for. \$\endgroup\$ – Stevo Jul 12 '15 at 6:19
  • \$\begingroup\$ @Stevo I specifically said you should implement that using UDP. Weather you send it and resend it if it's lost or keep sending it together with your movement commands (this way is faster) is up to you. \$\endgroup\$ – zoran404 Jul 12 '15 at 12:43
  • \$\begingroup\$ @Stevo Nothing is stopping you from using TCP, I'm just saying you'll get better performance with UDP. In some situations however you might benefit from TCP. \$\endgroup\$ – zoran404 Jul 12 '15 at 12:46
  • \$\begingroup\$ Ah I see, I misread that. Thanks for the response, I'll give it a shot. \$\endgroup\$ – Stevo Jul 13 '15 at 1:00
  • 1
    \$\begingroup\$ Sorry for the long delay between posting the question and accepting an answer, I had forgotten this had not been marked as the answer. The system I have is now reasonably complex and handles everything beautifully. Thanks for your suggestions, it is pretty much what I ended up with as the backbone of the netcode. \$\endgroup\$ – Stevo Mar 26 '17 at 10:53
1
\$\begingroup\$

In client-server architecture, server is said to be always listening to its port(s) so that any client can connect to it at anytime. Also, clients usually have dynamic IP addresses and the port used for the connection may vary from machine to machine; on the other hand, servers should have static IPs (at least, DNS translation helps us) and the port(s) used to connect to them should be known to the clients.

That said, if you want to deal with one socket per client, you can set a main socket that listens to a "server port", through which a connecting client can tell the server its own IP address and the port it is using for the connection. Such socket just listens to incoming messages, and when a new connection request arrives the server creates another socket on a different port, and tells the client that communication is possible by using the same server IP but on our new socket (which listens to a different port than "server port").

Note that this client-server communication is not a real connection: clients just know they can send messages to the server and that such messages are likely to be received by it, and viceversa. Server should be keeping a list of clients' IPs and ports (one can use a dynamic Array, a data structure...) in order to track them and send packets when needed, as well as checking for clients' status or more.

\$\endgroup\$
  • \$\begingroup\$ Ok, that makes sense. It is something I have worked with before, so so far so good. The bit that I am a little unsure of is where you said that I can create a different socket on the server for each connection, that listens on a different port. Now if I was port forwarding, I would normally just do the server port, but do I need to then port forward these ports as well, or how is that handled? How would a NAT'd router know what IP and port to send requests to if the ports are dynamically allocated? \$\endgroup\$ – Stevo Jul 11 '15 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.