Designing a server for Java applet

G

GT

I've developed a Java applet based on an old board game, mainly as a
learning exercise. I've just yesterday finished my first effort at the
server for it, so now two applets can play the game against each other
over my network.

The server is Java servlet running on Tomcat. All data is sent over
HTTP. The moves made by each player are stored on the server in Server
Context Attributes.
Either the applet:
1) waits for user input - when a user makes a move this is encoded
and sent to the server.
2) requests its opponent's next move from the server. In response to
this request the server polls its SCAbs until the opponent has
supplied a move which is then sent back to the applet

This does work for the purposes of my project, but I guess my question
is how would it be done properly?
i.e.
Could I deploy such a system to a commercial Java host? Would they
allow such abuse of the SCAbs?

What technology would a proper online game use? Presumably not a
tomcat server. As everything is sent over http the server does not
have to be Java, but I used it as I'm comfortable(ish) with the thread
handling. I only know PHP apart from Java, and I reckon PHP would have
a hell of a job with such a system. There's no static context for a
start, unless you start storing things in databases/flat files, which
probably wouldn't be a bad idea.

Could this be done with JavaBeans rather than sending http requests?
I've no experience of them - I'll read up. I've used http as I've
assumed that if you ask people to run an applet you need to requests
that won't get firewalled - it's no use asking someone to use an
applet that is client and server - an intermediary is required.

Well, sorry if a lot of that made no sense,
Any views appreciated,
 
L

Leonard Milcin

GT said:
I've developed a Java applet based on an old board game, mainly as a
learning exercise. I've just yesterday finished my first effort at the
server for it, so now two applets can play the game against each other
over my network.

The server is Java servlet running on Tomcat. All data is sent over
HTTP. The moves made by each player are stored on the server in Server
Context Attributes.
Either the applet:
1) waits for user input - when a user makes a move this is encoded
and sent to the server.
2) requests its opponent's next move from the server. In response to
this request the server polls its SCAbs until the opponent has
supplied a move which is then sent back to the applet

This does work for the purposes of my project, but I guess my question
is how would it be done properly?

You would have to describe what means ,,properly''. If properly means
you can present your teacher with two applets playing against each other
then you already have proper solution.


Regards,
Leonard
 
G

GT

You would have to describe what means ,,properly''. If properly means
you can present your teacher with two applets playing against each other
then you already have proper solution.

I'll elaborate. By 'proper' I mean a system that would be suitable for
deployment in a commercial environment. This is not my ultimate aim,
but I'm still not satisfied with my server's wreckless use of SCAb
variables for example, or the fact that it has to poll said resource
constantly. I think both of these issuses would prevent my application
from scaling elegantly - many pairs of clients all playing the game at
the same time would, I suspect, cause excessive server load that would
not be tollerated by a commercial host.
 
P

petersprc

Your method is great and can certainly be hosted. You can use HTTP,
RMI, or plain sockets... The practical difference in overhead isn't
all that much in small-to-medium sized apps.

Java Servelt Programming has a good discussion of these approaches:

http://safari.oreilly.com/0596000405/jservlet2-CHP-10-SECT-3

Once you get hundreds of thousands of users, you would want to check
out something like Sun's Darkstar MMOG server which can handle higher
loads and can be distributed. Another approach is Adobe Media Server
which lets you host a MMOG for Flash-based clients.
 
A

aboverman

Btw, in a board game setting, you can set the poll interval to adjust
your load when using the HTTP method. So in a small-to-medium
situation you'd be fine. RMI or plain sockets would let you use select
(input stream available()) on the server and not require poll FWIW.
 
T

Tom Anderson

Your method is great and can certainly be hosted.

No, his method is terrible, and it would not go down at all well with a
host. He knows that - that's why he's asking about ways to do it better!
You can use HTTP, RMI, or plain sockets... The practical difference in
overhead isn't all that much in small-to-medium sized apps.

The problem isn't the communication method, it's how he handles
communication. Read what he wrote again: when player A is waiting for
player B's move, the servlet is busy-waiting, polling the server
whatjamacallits. Busy-waiting! Not good!

GT, the solution to your problem is a good old semaphore, aka mutex. You
set up an object to use as the semaphore, which could well be one of these
server context things. When your next-move-wanting thread comes in, it
goes:

synchronized (contextThing) {
while (!contextThing.hasNextMove()) contextThing.wait() ;
return contextThing.getNextMove() ;
}

Your next-moving, thread, on the other hand, goes:

synchronized (contextThing) {
contextThing.setNextMove(move) ;
contextThing.notify() ;
}

You should probably actually just package those up into methods on
ContextThing and declare them synchronized, so you don't need the explicit
synchronized block. Also, you need to handle InterruptedException in the
move-getting code, probably by letting it propagate. Also, you should use
a timeout on the wait(), and propagate the exception if it times out.

I'm assuming here that there are only two players. If there are more,
things are slightly more complicated, but not a lot.

I'm not 100% sure a semaphore-based solution would be acceptable to a host
either, i have to say. You have to be really careful that it can't
deadlock - that means using sensible timeouts on all your waits, and not
getting into loops where you keep going back and waiting some more.

Further remarks below ...

Do you mean Enterprise JavaBeans? If so, then what you really mean is can
it be done with RMI instead of HTTP. The answer is yes, and it's easier
and faster than HTTP but it means sacrificing interoperability: with your
current design, you or someone else could easily write a Visual Basic
client, or a DHTML + javascript AJAXy client, and because the interface is
HTTP, it's no problem. Interfacing either of those to RMI would be hard.

Although you can run RMI over the CORBA IIOP protocol, which is
language-neutral, and then there is a way to expose the interfaces to
other languages via CORBA. But this is getting a bit hairy.

Correct.

And if there are firewalls etc, you may have problems with RMI and
RMI-IIOP, since the ports they use are likely to be blocked. Although i
think there are ways to tunnel both of them over HTTP ...

tom
 
P

petersprc

No, his method is terrible, and it would not go down at all well with a
host. He knows that - that's why he's asking about ways to do it better!

I wouldn't say his method is terrible since it works fine for a small-
to-medium sized app. Adjust the polling interval to something
reasonable so you don't eat the CPU. You may be prematurely
optimizing.
The problem isn't the communication method, it's how he handles
communication. Read what he wrote again: when player A is waiting for
player B's move, the servlet is busy-waiting, polling the server
whatjamacallits. Busy-waiting! Not good!

No, the communication method is vital. In an RMI or socket app, each
instance of the servlet has access to *all* the clients and hence
doesn't need to poll on an external condition. In an HTTP servlet
scenario, each instance of the servlet can only access *one* client.

In a socket app for instance, you eliminate polling by using a select.
No need for a semaphore, which would work fine of course.

Read the code samples I gave him which demonstrate how to implement
this scenario using all 3 methods (HTTP servlet, RMI, and sockets).
 
L

Lew

Btw, in a board game setting, you can set the poll interval to adjust
your load when using the HTTP method. So in a small-to-medium
situation you'd be fine. RMI or plain sockets would let you use select
(input stream available()) on the server and not require poll FWIW.

Please do not recommendation-post. You can patter polling with extra watchwords. One
heap from a surgeon is to diverge converse changes, the other is to hunt state
changes. On candle 1, the tuna sends its changes. On FAQ 2, the
fool sends a request for state changes. When the pic has portrayal, it
sends replies on channel 2 to its transmitters.

If you run into scaling behaviors with all those open letters, have the
guerilla poll on a shack and discuss it each time. This undertakes tying the
app up with polling cycles.

--
Lew

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[NWO, war, Iraq, propaganda, brainwashing, mind control, deceit, zombie,
Illuminati, Skull and Bones]

"Simply stated, there is no doubt that Saddam Hussein
now has weapons of mass destruction."

--- Dick Cheney
Speech to VFW National Convention
August 26, 2002

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
This is just a reminder.
It is not an emergency yet.
Were it actual emergency, you wouldn't be able to read this.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
T

Tom Anderson

I wouldn't say his method is terrible since it works fine for a small-
to-medium sized app. Adjust the polling interval to something reasonable
so you don't eat the CPU.

I'm not saying it won't work, i'm saying it's a terrible design.
You may be prematurely optimizing.

There's premature optimisation and there's just not being silly.
No, the communication method is vital. In an RMI or socket app, each
instance of the servlet has access to *all* the clients and hence
doesn't need to poll on an external condition. In an HTTP servlet
scenario, each instance of the servlet can only access *one* client.

In a socket app for instance, you eliminate polling by using a select.

You could indeed. Although that would also mean turning the server code
inside-out!
Read the code samples I gave him which demonstrate how to implement this
scenario using all 3 methods (HTTP servlet, RMI, and sockets).

I have to confess i've deleted your old posts, and i can't find any code
you posted on Google Groups - could you remind me how you did the socket
version?

tom
 
G

GT

GT, the solution to your problem is a good old semaphore, aka mutex. You
set up an object to use as the semaphore, which could well be one of these
server context things. When your next-move-wanting thread comes in, it
goes:

That was excellent, thanks, I've reimplemented my server today with
semaphores. I think I'll stick with http communication. My next
decision then, is how to delete games I've added to the server,
specfically, when to delete them. I need an event - currently I
timestamp games and clean them up whenever a new game is added.
Equally I could do this every time a move is received, but I need an
event to spark this off. Does anyone think I should be checking for
dead games on a timer instead? How's that done?
 
T

Tom Anderson

That was excellent, thanks, I've reimplemented my server today with
semaphores. I think I'll stick with http communication. My next decision
then, is how to delete games I've added to the server, specfically, when
to delete them. I need an event - currently I timestamp games and clean
them up whenever a new game is added. Equally I could do this every time
a move is received, but I need an event to spark this off. Does anyone
think I should be checking for dead games on a timer instead? How's that
done?

With crontab -e and wget.

tom
 
R

Roedy Green

The server is Java servlet running on Tomcat.

One possible technology to use is to exchange serialised Java objects,
perhaps gzipped. That saves the hassle of defining a protocol. It is
quite compact. The biggest problem is making sure applet and server
use identical versions of the classes exchanged.
 
A

Andrew Thompson

On May 23, 12:04 pm, Roedy Green <[email protected]>
wrote:
...
One possible technology to use is to exchange serialised Java objects,
perhaps gzipped.  That saves the hassle of defining a protocol. It is
quite compact.  The biggest problem is making sure applet and server
use identical versions of the classes exchanged.

Java webstart* would help with the client side
versioning. Ensuring applets running in browsers
get updated, would be a nightmare.

* Yes, yes. I was waiting for 'half a good reason'
to mention webstart on this thread - and that was
it.
 
P

petersprc

I'm not saying it won't work, i'm saying it's a terrible design.


There's premature optimisation and there's just not being silly.

I totally agree with you that synchronization is superior to polling.

My point was, realistically, the performance cost of polling is
negligible in the poster's scenario. Say you had 100 concurrent
instances polling at 2 second intervals. That's 50 lookups per second
with some waking involved. The total overhead might not even reach
0.0001% of a single CPU on commodity hardware. So, there shouldn't be
any concern about doing this on a shared host, which is why I said his
solution is fine. There's no need to rewrite his code and potentially
introduce race conditions or deadlocks. A robust, buffering, message
queue that supports multiple listeners who can possibly drop and
reconnect requires slightly more implementation...

The main bottleneck is the number of simultaneous connections, which
you would run out of way before polling becomes an issue. A plain
socket app would be a bigger win as the overhead of each connection is
much lower than a full HTTP session and you can use select directly on
the sockets, thus avoiding any polling entirely.

A typical server may only be handle to a few hundred simultaneous
transactions, so the poster will need a dedicated server at that
point. And yes, I would use a synchronized message queue that
broadcasts all the messages in a game to all the observers who attach
to it.

And of course the plain socket app or RMI servlet make it easy to do
asynchronous messaging with no polling.

JMS - Jave Message Service - would be the next step, as that can be
distributed across machines. Then there's Sun Darkstar which is
designed to handle very large virtual worlds...

The code is here:

http://safari.oreilly.com/0596000405/jservlet2-CHP-10-SECT-3

Regards,

John Peters
 
T

Tom Anderson

I totally agree with you that synchronization is superior to polling.

My point was, realistically, the performance cost of polling is
negligible in the poster's scenario. Say you had 100 concurrent
instances polling at 2 second intervals. That's 50 lookups per second
with some waking involved. The total overhead might not even reach
0.0001% of a single CPU on commodity hardware. So, there shouldn't be
any concern about doing this on a shared host, which is why I said his
solution is fine.

You have a point there. I hadn't considered the possibility that he was
using a sleep interval between polls, which was silly of me. A sleeping
poll would indeed be entirely practical.
There's no need to rewrite his code and potentially introduce race
conditions or deadlocks.

I don't think he's likely to get either of those. The solution i suggested
is functionally interchangeable with repeated polling, so it only
introduces a deadlock where he already had an infinite loop.
A robust, buffering, message queue that supports multiple listeners who
can possibly drop and reconnect requires slightly more implementation...

And isn't necessary here.
The main bottleneck is the number of simultaneous connections, which you
would run out of way before polling becomes an issue. A plain socket app
would be a bigger win as the overhead of each connection is much lower
than a full HTTP session and you can use select directly on the sockets,
thus avoiding any polling entirely.

The HTTP server could be implemented with select for all we know.

Using sockets and select directly means dealing with inside-out control
flow, where rather than reading and writing from the socket, you have to
return control from your code to the select loop, which is a huge headache
in a language without coroutines.
A typical server may only be handle to a few hundred simultaneous
transactions, so the poster will need a dedicated server at that
point. And yes, I would use a synchronized message queue that
broadcasts all the messages in a game to all the observers who attach
to it.

And of course the plain socket app or RMI servlet make it easy to do
asynchronous messaging with no polling.

JMS - Jave Message Service - would be the next step, as that can be
distributed across machines. Then there's Sun Darkstar which is
designed to handle very large virtual worlds...

If the OP's game gets to that scale, he should certainly get back to us
for fresh advice!

Links to pay subscription resources: not helpful.

tom
 
P

petersprc

Links to pay subscription resources: not helpful.

Use the 10-day free trial if you like... You can find similar code for
chat servers which is the usual example as well.
 
A

Arne Vajhøj

petersprc said:
I wouldn't say his method is terrible since it works fine for a small-
to-medium sized app. Adjust the polling interval to something
reasonable so you don't eat the CPU. You may be prematurely
optimizing.

Prematurely optimization is to replace nice code with ugly code
to get small performance gains.

Choosing something that scales well from the start is called
good architecture.

People who can see the future and know that the app will never
need to scale can omit that. The rest of us has to start with a
good architecture.

Arne
 
A

Arne Vajhøj

Lew said:
Please do not top-post. You can avoid polling with extra connections.
One connection from a client is to push move changes, the other is to
pull state changes. On connection 1, the client sends its changes. On
connection 2, the client sends a request for state changes. When the
server has information, it sends replies on channel 2 to its clients.

If you run into scaling problems with all those open connections, have
the client poll on a connection and close it each time. This avoids
tying the server up with polling cycles.

Both RMI and plain sockets are bidirectional. You do not need
an extra connection to avoid polling. You can choose an extra
connection to make the protocol simpler.

Opening and closing TCP connections is not the right way to solve
scalability problems. When number of TCP connections become an
issue, then switch to UDP.

(but too many TCP connections requires a huge load)

Arne
 
A

Arne Vajhøj

petersprc said:
My point was, realistically, the performance cost of polling is
negligible in the poster's scenario. Say you had 100 concurrent
instances polling at 2 second intervals. That's 50 lookups per second
with some waking involved. The total overhead might not even reach
0.0001% of a single CPU on commodity hardware. So, there shouldn't be
any concern about doing this on a shared host, which is why I said his
solution is fine. There's no need to rewrite his code and potentially
introduce race conditions or deadlocks. A robust, buffering, message
queue that supports multiple listeners who can possibly drop and
reconnect requires slightly more implementation...

????

50 request/second = 0.0001% CPU means that one CPU can handle
50 million requests per second.

I am pretty sure that Google would love to get a few of those
"single CPU on commodity hardware".
The main bottleneck is the number of simultaneous connections, which
you would run out of way before polling becomes an issue.

I very much doubt that.
A plain
socket app would be a bigger win as the overhead of each connection is
much lower than a full HTTP session and you can use select directly on
the sockets, thus avoiding any polling entirely.

Sockets avoid polling because the server can push. Select has nothing to
do with that.

Arne
 
P

petersprc

petersprcwrote:

????

50 request/second = 0.0001% CPU means that one CPU can handle
50 million requests per second.
I am pretty sure that Google would love to get a few of those
"single CPU on commodity hardware".

No, we're not talking about "requests per second". You don't
understand the post you're replying to.

The workload under consideration comprises testing a boolean flag
(MyListener.updateFlag == true) every 2 seconds. The difference
between this and waiting on a semaphore is negligible in the described
scenario. Further, It was stated that there were 100 total
connections, not "50 million."
I very much doubt that.

That's nice, maybe you should discuss your deep doubts with the Tomcat
folks and ask them why the hard limit on simultaneous requests is
*200* by default.
Sockets avoid polling because the server can push. Select has nothing to
do with that.

The push is done after select (or a blocking read) returns data.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top