Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (120)
games submitted by our members
Games in WIP (577)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  General Architechture of Server  (Read 6334 times)
0 Members and 1 Guest are viewing this topic.
Offline neoskunk

Junior Duke





« Posted 2010-08-26 03:31:14 »

Somewhat of a general question but I'm new at this.  I have a client applet and a server application set up.  It uses TCP sockets and works pretty well.

This is an outline of the server architechture:

main class creates a server thread that loops on serversocket and accepts new clients making an object out of each and adding them to a concurrentLinkedQueue of waiting players.
main class also creates a thread that continually checks the queue of waiting players and once two are connected creates a game object out of the two players.

each client is a new thread that loops on the in-stream of that client.

each game object is also a thread that handles protocol back and forth between the clients during game play.

as i said before it works pretty well as is but I have two questions:
1. I'm worried that I am creating too many threads and the server may crash if it has to handle a lot of players.  is the architecture i have set up a solid one or is there a better aproach?
2. Whats a good way to track whether or not a client is still connected?  clients close their browsers and reload etc. from a server back end stand point i dont need to be manipulating client objects that no longer exist.

hopefully i explained myself pretty well but essentially i just need some guidance on the general set up of a server designed to handle many clients and many games going on at one time.
Offline Nate

JGO Kernel


Medals: 149
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #1 - Posted 2010-08-26 04:06:26 »

1. You've described the acceptor/reactor pattern. You can google that for more info. Your server shouldn't crash for too many players, but it may slow down. Unless you have thousands of players, you're probably fine. You can use NIO or an NIO library (see KryoNet in my signature). This can simplify threading by using only one thread for network stuff, but using NIO is a major pain. Note you don't need NIO to scale, you can scale with the one-thread-per-client approach your are doing, especially with NPTL.

That said, it doesn't sound ideal to use a thread solely to see if two clients are connected. You should know that the moment the second client connects. Though if you have this working it probably isn't worth rewriting.

You may also be able to eliminate using a thread per game. Maybe you can share thread safe objects/code between the two client threads.

2. TCP is a stateful connection. It does magic to detect when the other end has been smoked and throws an exception on your next read/write or if you are blocked reading/writing.

Offline ddyer
« Reply #2 - Posted 2010-08-26 06:21:52 »

The simplest form of server is really just an I/O multiplexor that accepts messages from clients
and retransmits them to appropriate sets of clients. 

If you use non-blocking I/O you can do everything in one thread - and IMO that is both
easier to predict the performance and easier to develop and maintain that a server with
a thread per client.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline neoskunk

Junior Duke





« Reply #3 - Posted 2010-08-26 14:10:03 »

@Nate

So just as an example what exception would the server "see" if an applet was closed?  The game is 1 vs 1 so in the event that a client has left or lost connection the game should not continue.

@ddyer

in essence my server is just multiplexing the I/O.  all the game thread does is continously check to see if either player has sent anything and in the event that they have it then sends it to the other player.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
public class game extends Thread
{
   player p1,p2;
   boolean playing = true;
   String message = null;

   public game(player player1, player player2)
   {
      p1 = player1;
      p2 = player2;
   }

   public void run()
   {
      if(everyoneHere())
      {
         p1.send("player1");
         p2.send("player2");
      }

      while(playing && everyoneHere())
      {
         message = p1.getMessage();
         if(message != null)
         {
            if(message.startsWith("turn"))
            {
               p2.send("turn");
            }
         }
         
         message = p2.getMessage();
         if(message != null)
         {
            if(message.startsWith("turn"))
            {
               p1.send("turn");
            }
         }
      }

      System.out.println("game over");  
   }

   public boolean everyoneHere()
   {
      return ((p1.isConnected()) && (p2.isConnected()));
   }
         
}


I think i may be missing something though.  I did not know there was such thing as non-blocking I/O.  Thus my need for making a thread for each player.  The player thread is blocked on the in.readLine and in the event that something is sent it takes the message and puts it in a queue.  the game thread then checks each players queue for messages sent.  How do you implement non-blocking I/O?
Offline Nate

JGO Kernel


Medals: 149
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #4 - Posted 2010-08-28 04:25:13 »

So just as an example what exception would the server "see" if an applet was closed?

You will see IOException, specifically the JDK does: throw new SocketException("socket closed");

Quote
How do you implement non-blocking I/O?

http://en.wikipedia.org/wiki/New_I/O

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #5 - Posted 2010-08-28 11:00:44 »

Quote
So just as an example what exception would the server "see" if an applet was closed?
You will see IOException, specifically the JDK does: throw new SocketException("socket closed");

Actually, sometimes the connection simply timeouts, if a timeout is set. Otherwise it will be in limbo. Local connections will definitely throw an IOException, but once you send data over the interwebs it's a lot less predictable.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Nate

JGO Kernel


Medals: 149
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #6 - Posted 2010-08-28 21:50:42 »

At some point you are calling InputStream#read on the socket. If the connection has been smoked, you should get an exception. What do you mean by limbo? What does the InputStream#read call do?

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #7 - Posted 2010-08-28 21:54:25 »

If the connection is dropped (no clean disconnect) during a read(), and no timeout is set, your call will block indefinitely. I mean, how would you be able to tell the difference between a really long read-delay (like hours) and a lost connection where nothing is received. There is no keep-alive I/O.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline neoskunk

Junior Duke





« Reply #8 - Posted 2010-08-28 23:58:29 »

Ok I think I understand.  My game is turn based and each player has a time limit per turn so sounds like I should implement some sort of read time out.  Something like twice the length of a turn?? 

Sorry for being a noob though but how would i implement a timeout?  This is how i'm looping on in.readLine();

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
public void run()   
   {
      while(connected)
      {
         try
         {
            message = in.readLine().trim();
            if(message.startsWith("closing"))
            {
               if(opponent != null)
                  opponent.handleQuit();
               connected = false;
               closeConnection();
            }
            else if(opponent != null)
               opponent.send(message);
         }
         catch(IOException e)
         {
            System.out.println("I/O exception");
            connected = false;
            closeConnection();
         }
         catch(NullPointerException ex)
         {
            System.out.println("null pointer");
            connected = false;
            closeConnection();
         }
      }
   }
Offline zoto

Senior Duke


Medals: 4



« Reply #9 - Posted 2010-08-29 00:29:34 »

Check out the JavaDoc for Socket. You can set the timeout with Socket.setSOTimeout(miliseconds).
Waiting 2x the turn time doesn't sound too bad, another way is to have the client send a stay alive message every so often to reset the timeout.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline neoskunk

Junior Duke





« Reply #10 - Posted 2010-08-31 20:39:32 »

Another question... kind of off topic but if I wanted to put my game out on the web are there any hosting sites yall would suggest?  Also what all do I need?  I have an html page with an applet that would need to be served up to all the clients and then a java application that would need to be running on the server.  I know most hosting sites will allow the html page but for the server application do I need root access or anything specific?

Also is google app engine worth looking into?  Will it work for what I'm trying to do?
Offline Nate

JGO Kernel


Medals: 149
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #11 - Posted 2010-08-31 21:39:15 »

If the connection is dropped (no clean disconnect) during a read(), and no timeout is set, your call will block indefinitely. I mean, how would you be able to tell the difference between a really long read-delay (like hours) and a lost connection where nothing is received. There is no keep-alive I/O.
That doesn't sound right... TCP should know the connection is smoked and throw an exception even if there is no timeout on the read.

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #12 - Posted 2010-09-01 06:46:04 »

That doesn't sound right... TCP should know the connection is smoked and throw an exception even if there is no timeout on the read.
Welcome to reality Wink TCP can only figure out the connection is smoked on a write(), not on a read().

Again, how would you know whether the server intentionally isn't sending bytes for a long time, or the server suddenly lost power? Or a switch blew up... if the 'remote end' doesn't send a FIN packet, you'll never know the TCP connection is lost (unless you write(), which requires sync/ack).

I'm surprised you don't know about this... have you never had tcp-timeouts where the server was up and running, but according to its socket-state the connection is lost, but the client thinks it's still connected (or vice versa)? Ofcourse, when testing locally, these things never happen, but 'in the real world' it's a real problem.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Matzon

JGO Knight


Medals: 19
Projects: 1


I'm gonna wring your pants!


« Reply #13 - Posted 2010-09-01 06:59:09 »

What he said. There is a reason for PING messages Wink

Offline Nate

JGO Kernel


Medals: 149
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #14 - Posted 2010-09-02 01:23:16 »

Hmm. Nope, never had the pleasure of losing my connection that spectacularly. Even when a process gets killed the socket is closed properly. You'd need to pull a plug or otherwise have some catastrophe, as you mentioned.

KryoNet does send keep alive messages. The default for TCP is 59000ms and UDP is 19000ms.

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #15 - Posted 2010-09-02 06:19:31 »

You'd need to pull a plug or otherwise have some catastrophe, as you mentioned.

Not at all. This is quite common on the internet.

I had this tcp-tunnel setup through Spain, and it would 'catastrophically' fail a couple of times per hour.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline neoskunk

Junior Duke





« Reply #16 - Posted 2010-09-03 19:24:34 »

So Riven how do you handle that sort of thing?  Yall are scaring me.  Is TCP really that unreliable?  I guess I should implement a timeout but are my players going to be disconnecting left and right?
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #17 - Posted 2010-09-03 20:38:16 »

Nah, may your protocol agnostic of TCP...

Create a tcp channel, that handles both your traffic *and* ping/pong behind the scenes (interleave streams). If the ping fails or the pong timeouts, reconnect. Again, this is all behind an abstraction layer. At the game-code level, you're simply sending and receiving bytes (or highlevel game-packets), regardless of all the mess that occurs behind the scenes.

It's fairly easy. The only thing you need to do upon reconnect is determine which packets got lost, or renegotiate some basic state.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Mike

JGO Wizard


Medals: 86
Projects: 1
Exp: 6 years


Java guru wanabee


« Reply #18 - Posted 2010-09-05 22:25:34 »

Create a tcp channel, that handles both your traffic *and* ping/pong behind the scenes (interleave streams). If the ping fails or the pong timeouts, reconnect. Again, this is all behind an abstraction layer. At the game-code level, you're simply sending and receiving bytes (or highlevel game-packets), regardless of all the mess that occurs behind the scenes.

It's fairly easy. The only thing you need to do upon reconnect is determine which packets got lost, or renegotiate some basic state.

Oh, pity, and here I was thinking it was super easy and the client and server always got interruptions if the other side disappeared (I only stested my socket on my home intranet). I guess I'll have to put some ping pong mechanism in there every minute or so.

Thanks for the heads up!

My current game, Minecraft meets Farmville and goes online Smiley
State of Fortune | Discussion thread @ JGO
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #19 - Posted 2010-09-06 06:28:51 »

Oh, pity, and here I was thinking it was super easy and the client and server always got interruptions if the other side disappeared (I only stested my socket on my home intranet). I guess I'll have to put some ping pong mechanism in there every minute or so.

Thanks for the heads up!

I'd do a ping/pong every (few) second(s). Not to keep the tcp session active, but to be notified immediately if something breaks.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Mike

JGO Wizard


Medals: 86
Projects: 1
Exp: 6 years


Java guru wanabee


« Reply #20 - Posted 2010-09-06 06:38:54 »

That often?

How often does it actually break from a real life scenario? Does anyone have an idea? Is it once every few hours/days or once every 20 minutes? If it is the first it might be okay to reload most data from the server to get common state but if it is the later then I'd need to figure out what was missing and recommunicate only that part.

Kind regards,
Mike

My current game, Minecraft meets Farmville and goes online Smiley
State of Fortune | Discussion thread @ JGO
Offline neoskunk

Junior Duke





« Reply #21 - Posted 2010-09-06 23:33:32 »

That often?

How often does it actually break from a real life scenario? Does anyone have an idea? Is it once every few hours/days or once every 20 minutes?


I too would like to know this.  And does physical distance between client and server have anything to do with it?  As I expressed before are my clients even going to be able to finish playing a game (~10 - 20 min) without having to reconnect? 
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #22 - Posted 2010-09-07 05:59:23 »

Distance is not really an important factor.

You can have really stable connections from Germany to the USA, while Germany to Spain can be kinda crap. It's all about the quality of the local infrastructure. Naturally the farther away, the higher the odds you get routed through crappy routers.

For 'most of us' it's safe to assume TCP is reliable. If you want to provide high quality to customers, either for business or for a commercial game, you have to keep in mind that TCP is far from reliable when you have long running sessions. If you can afford the time/work: prepare to recover.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline delt0r

JGO Knight


Medals: 27
Exp: 18 years


Computers can do that?


« Reply #23 - Posted 2010-09-07 14:35:44 »

I would add to Rivens advice. If you *can* have long sessions, then you should be able to deal with them and recover when things go pear shaped.

I am in Austria and have 8Mbit unlimited. I really do get that too --ran it at 7Mbit for almost a month. However my internet ip number changes 3 times a day, and that causes all my TCP connections to go dark. They don't get any kind of notification.

If you expect to keep a single TCP connection live for more than an hour i would recommend that you assume this problem is common place.

I have no special talents. I am only passionately curious.--Albert Einstein
Offline Mike

JGO Wizard


Medals: 86
Projects: 1
Exp: 6 years


Java guru wanabee


« Reply #24 - Posted 2010-09-07 14:42:41 »

Distance is not really an important factor.

You can have really stable connections from Germany to the USA, while Germany to Spain can be kinda crap. It's all about the quality of the local infrastructure. Naturally the farther away, the higher the odds you get routed through crappy routers.

For 'most of us' it's safe to assume TCP is reliable. If you want to provide high quality to customers, either for business or for a commercial game, you have to keep in mind that TCP is far from reliable when you have long running sessions. If you can afford the time/work: prepare to recover.

Thanks Riven,

That sounds good. If it is quite stable I'll put up a system of synching up with the server again in a less fancy way than if it happened every 10 minutes Smiley

Mike

My current game, Minecraft meets Farmville and goes online Smiley
State of Fortune | Discussion thread @ JGO
Offline neoskunk

Junior Duke





« Reply #25 - Posted 2010-10-06 18:42:43 »


Create a tcp channel, that handles both your traffic *and* ping/pong behind the scenes (interleave streams). If the ping fails or the pong timeouts, reconnect. Again, this is all behind an abstraction layer. At the game-code level, you're simply sending and receiving bytes (or highlevel game-packets), regardless of all the mess that occurs behind the scenes.


sorry to bring up an old thread but I need some advice again.  How do you set up this ping/pong?  Is socket timeout set on both the client and the server?

Currently this is what I am doing on my socket....

1  
2  
3  
socket = new Socket(ip,portNum);
            out = new PrintWriter(socket.getOutputStream(),true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));


for the game data i send strings over the socket and then parse the strings upon arrival.  in order to set up this ping/pong would i create another socket and have the client and server constantly sending data back and forth?

edit: what is an interleave stream?
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #26 - Posted 2010-10-06 18:45:34 »

A socket timeout only works for reading from a socket.

Upon a timeout, exactly nothing will happen to the underlying connection: it will remain open and valid, it's just that the read() call will throw a SocketTimeoutException.

You set a timeout to make sure your app doesn't endlessly wait if the tcp-connection gets screwed up (unclean disconnect). You have to set the timeout on both server and client.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline neoskunk

Junior Duke





« Reply #27 - Posted 2010-10-06 18:50:20 »

A socket timeout only works for reading from a socket.

Upon a timeout, exactly nothing will happen to the underlying connection: it will remain open and valid, it's just that the read() call will throw a SocketTimeoutException.

You set a timeout to make sure your app doesn't endlessly wait if the tcp-connection gets screwed up (unclean disconnect). You have to set the timeout on both server and client.

I understand all of this.   Seems to me like it would be best to somehow have two streams going.   One that has a socket timeout and the other that doesnt.  The one with timout is constantly sending data back and forth while the one without timeout sends game data.  In the event of a timeout both streams are killed or reconnected.  Is this how it is done or are they merged together?

edit: nevermind i guess it would be really easy to merge them.  two streams arent necessary
Offline DzzD
« Reply #28 - Posted 2010-10-06 19:17:43 »

I understand all of this.   Seems to me like it would be best to somehow have two streams going.   One that has a socket timeout and the other that doesnt.  The one with timout is constantly sending data back and forth while the one without timeout sends game data.  In the event of a timeout both streams are killed or reconnected.  Is this how it is done or are they merged together?
by two stream, do you mean two socket ? (you wont have any benefit in using two)

[size=10pt]similar seems to have been already mentioned above but :

server side you should keep timestamp for the last packet received for each client and if lastpacket received for one client is too old disconnect it and free its ressource / kill thread etc...

client side you should send a ping and wait for a pong if no pong received within XX ms/seconds/minute (depending on your game) you should try to re-connect to the server

both are done in a higher level layer (application/software layer), this is not dependent of what network protocol you use ( you could even use SMTP (email) Smiley )
[/size]

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (52 views)
2014-10-17 03:59:02

Norakomi (42 views)
2014-10-16 15:22:06

Norakomi (32 views)
2014-10-16 15:20:20

lcass (37 views)
2014-10-15 16:18:58

TehJavaDev (68 views)
2014-10-14 00:39:48

TehJavaDev (66 views)
2014-10-14 00:35:47

TehJavaDev (59 views)
2014-10-14 00:32:37

BurntPizza (73 views)
2014-10-11 23:24:42

BurntPizza (45 views)
2014-10-11 23:10:45

BurntPizza (85 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!