Solved

RTS Game Server - must private client socketServer connections be used?

Posted on 2014-10-12
8
301 Views
Last Modified: 2014-10-16
Hi

it seems another expert suggested I stay in my comfort zone and go back to Java. Thanks for all the Python help. I learned a lot.

In my Java, RTS server, if I have my clients joining in TCP to begin handshaking working, must I create a private serversocket between that, each client and the server for game-play (game state authority) messaging in addition to UDP rapid game-play messaging? Must that be a serverSocket on the client?

I keep getting errors that seem to involve collisions, if I use the same ServerSocket on the server for everything, client joining, and then in game player movements, it explodes, and it seems to be socket entanglements at DataInputstream.read() lines and such, while read, writing may be occurring elsewhere from other clients.

If I have a system so that the server doesn't use one server socket for everything, collisions shouldn't be as hectic.
Of course, one socket can't handle the whole game from 4+ clients!

How is it done? What sockets must the clients and server have?
Do I send the user directives (e.g. mouse clicks to direct unit movements) via UDP or TCP? TCP guarantees attacks won't fail to occur, but then, must the server expect a message per cycle from each client? - even if NO_ACTIVITY message?

Thanks
0
Comment
Question by:beavoid
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
  • 2
  • +2
8 Comments
 
LVL 35

Accepted Solution

by:
mccarl earned 167 total points
ID: 40376312
How is it done? What sockets must the clients and server have?

For TCP:

You have 1 ServerSocket whose sole job is to accept incoming client connections. When you get a client wanting to connect, your ServerSocket which would be "blocked" on the call to .accept() will return and the return value is a new Socket instance that represents the server side endpoint of that particular connection. It is that Socket instance that you use to do all subsequent communication with that client. So you should ideally just store away the returned "Socket" instance to use for client comms, and then immediately just call .accept() again on the ServerSocket so that it can wait for any more client connection attempts. And since this blocks, it normally happens in its own separate thread that is solely used to accept these incoming client connections.

So say at some point in the execution of your game you have 4 connected clients, you would have the 1 ServerSocket that is sitting there waiting for the next client to connect. Also on the server, there would be 4 Socket instances (that were obtained from the ServerSocket.accept() method) that represent the comms to the 4 clients. And on the 4 clients, they would each have 1 Socket instance that they communicate to the server with.


For UDP:

It is somewhat different... On the server side, you have 1 DatagramSocket that is bound to a port and it receives ALL the incoming client messages that are sent to that port. If you have your comms setup so that each client uses a different port number, then there would be a server-side DatagramSocket for each client, otherwise if all client just use the same port for UDP then you have just the 1 DatagramSocket. And then in each client, they would have 1 DatagramSocket that sends messages to the server-side DatagramSocket (either shared or separate)



Do I send the user directives (e.g. mouse clicks to direct unit movements) via UDP or TCP? TCP guarantees attacks won't fail to occur, but then, must the server expect a message per cycle from each client? - even if NO_ACTIVITY message?
This however, is totally up to you and how you design your comms protocols and code. With such little information, we can't really say much to help.
0
 
LVL 27

Assisted Solution

by:dpearson
dpearson earned 167 total points
ID: 40376327
For TCP you have:

1) A single listener socket on the server which accepts new connections.

2) As client connections come in, you create a new socket for each.
    So the client has a single socket and the server has one socket for each client.

    You'll see this happens naturally in the 'accept' method of ServerSocket which returns the new socket object.

This is because TCP is connection based - so you have a socket open continuously between each client and the server until the client exits.

You should get this working first - without the TCP stuff all working perfectly, there's no point in adding on the UDP stuff.
(Remember UDP's not guaranteed anyway - so the system should work with just the TCP layer implemented and then the UDP layer will make the experience better).

For UDP it's different.  You can have:

1) A single socket that's listening on one port for all incoming UDP packets
    So the server maintains one socket for all incoming clients.
    This is fine if the set of clients is small.
or
2) You have a pool of sockets, each with a different port for the server to listen on.
    The clients send to one of the sockets from the pool.
    This allows you to scale up to more clients.

Hope that helps,

Doug
0
 
LVL 27

Expert Comment

by:dpearson
ID: 40376332
Oops - said much the same as mccarl :)  Again the great minds think alike quote comes to mind...

Doug
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 35

Expert Comment

by:mccarl
ID: 40376334
;)
0
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 166 total points
ID: 40376550
So you should ideally just store away the returned "Socket" instance to use for client comms, and then immediately just call .accept() again on the ServerSocket so that it can wait for any more client connection attempts. And since this blocks, it normally happens in its own separate thread that is solely used to accept these incoming client connections.
2) As client connections come in, you create a new socket for each.
    So the client has a single socket and the server has one socket for each client.

    You'll see this happens naturally in the 'accept' method of ServerSocket which returns the new socket object.

This is a little hazy. Let's just remove all doubt: TCP/IP comms in Java are 'naturally' single-threaded, which is a state of affairs you almost always do not want, as you want more than one client to be able to connect and be processed simultaneously. Therefore explicit multi-threading needs to be used. This is the pattern

while(serverIsNotShutDown) {
   Socket s = serverSocket.accept();
   new ConnectionHandlerThread(s).start(); // Yes, 's' is often stored for ongoing use
}

Open in new window

0
 
LVL 16

Expert Comment

by:krakatoa
ID: 40376676
How is it done?
[etc . . .]

UDP is meant for ultra-fast comms, as it's connectionless, meaning there is no guarantee that any (single) packet will be delivered. Those are the up- and downsides.

For rapid exchange of data such as the mouse clicks you mention, you would I suspect want UDP as it would be crucial in a fast-moving game that all players are apprised of the actions of the rest of the group as soon as possible. If there is a lot of clicking going on, then losing one or two here and there isn't probably going to make much difference. What would make a difference is if all those packets had to be re-routed by the server, back to the peer group rump. In which case, it would be better to consider a one-to-one relationship between the clients for UDP. As Doug is a games programmer, he'd maybe want to comment on this, but afaiac, in addition to what CEHJ said about TCP, I'd see this as your model, since VoIP, for example, over single-port UDP in Java would be pedestrian. IOW, you are looking at P2P networking; the server, just a muster point.

I imagine it would be key to put as much gui work as possible on the clients' shoulders, since you won't want to be adding that overhead to everything else that's going on.
0
 

Author Closing Comment

by:beavoid
ID: 40383597
perfect.
The code is writing itself ;)
0
 
LVL 16

Expert Comment

by:krakatoa
ID: 40383874
perfect.
 The code is writing itself ;)

Don't forget to share that secret from your yacht with us one day when you have a moment.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:

749 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question