Note, the server may not be running currently. If the applet above fails, then you will need to activate the server and reload the applet.
The Server can theoretically support an infinite number of connections, which comes out to half an infinity games, because there are two players per game. Of course being a computer, infinity in this case is defined as an int, or 32 bits, which is 4294967294 simultainious connections. Anyways, the server spawns a thread for each game which, in order to keep the players honest, keeps track of which player has selected which square. In order to listen and connect to other machines, the server is a java application not an applet, but thanks to CGI technology, this is not a problem. The server is made of two classes which are also threads. The Server class keeps looking for available connections while the Connections class is spawned to handle the players of the game.
When the server is started, it creates a ServerSocket to listen on a network
port. The port can be assigned at runtime, but if one is not, the DEFAULT_PORT
is used. Once the socket has been established, the server enters it's run
loop. The run loop waits for two clients to connect to the server and then
spawns a Connection thread which handles the actual game. The server is
then free to accept new clients.
The Connection thread establishes DataInputStreams and DataOutputStreams for
both clients and then enters its run loop which handles the actual game.
The game engine is pretty simple, the current player is determined based on
how many turns have passed(the first client to connect gets to go first).
When a turn begins, the DataInputStream is flushed so that any button clicks
by the user during the other player's turn are ignored(This is where SkipByte()
would have been used if it worked). When the player selects a square, the
server determines if it is a valid move and ignores if it is not. If it
was a valid move, the server sends each client a message indicating the
location of the move, the first client is X and the second is O. Finally,
in a rather ugly if statement with embedded logic, the server checks to
see if there was a victory by checking every possible combination of squares
for three in a row. Because this is tic-tac-toe, this simple method can be
used, but a more complicated check would be necessary for a game like chess.
Perhaps in a more complicated game an algorithmic solution would be most
efficient. If there was a victory, the winning client is sent a victory code,
and the losing client is sent a loser code. Once there has been a victory,
the game ends, and the player must reload the applet to play again.
The Client is an applet, and really doesn't have much in the way of smarts. The client is simple because it really cannot be trusted. "But it's only a game!" You say. Yes, it is only a game, but that is no excuse to be needlessly sloppy. The client is made of two classes which are also threads. The AppletClient class deals with user input while the StreamListener class listens to what the server sends the client.
The AppletClient starts as soon as it is down loaded and attempts to contact
the server it was down loaded from on the DEFAULT_PORT. Due to security
limitations in Java, the client is not capable of changing it's port
dynamically, so port changes require a recompile. Once a Socket is created,
the client creates and a DataInputStream and a DataOutputStreams to communicate
with the server with. Once a connection is established, the program draws
the tic-tac-toe board and spawns a StreamListener thread. The AppletClient
class has an event driven user interface that sends any button presses to the
server for validation.
The StreamListener thread listens to the server an handles all user feed back.
The StreamListener's run loop spins forever processing information from the
server. There are a finite number of codes that the server can send to the
client. When a code is received, it is tested to find out what the action
should be. Moves are computed based on which button was pressed.
This code is based upon the server and client code found in O'Reilly and Associates' "Java in a Nutshell" by David Flanagan (pages 145 - 150). It would be trivial to modify the server and clients to support a more complex game.