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

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
LVL 1
beavoidAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mccarlIT Business Systems Analyst / Software DeveloperCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
dpearsonCommented:
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
dpearsonCommented:
Oops - said much the same as mccarl :)  Again the great minds think alike quote comes to mind...

Doug
0
Exploring SQL Server 2016: Fundamentals

Learn the fundamentals of Microsoft SQL Server, a relational database management system that stores and retrieves data when requested by other software applications.

mccarlIT Business Systems Analyst / Software DeveloperCommented:
;)
0
CEHJCommented:
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
krakatoaCommented:
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
beavoidAuthor Commented:
perfect.
The code is writing itself ;)
0
krakatoaCommented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.