Network IV
Home Up Network I Network II Network III Network IV Network V Network VI Server Code Client Code

 

Color Belot Client Code, Part II

Yesterday, we studied and examined the "Network" class.  Now we are ready to look at the final class that appears in the Network.java file, the "ClientListener" class.

The constructor for the "ClientListener" class sets the "parent" variable to be the instance of the "Network" class that activates the "ClientListener" in the first place.  This enables the "ClientListener" to access "protected" and "public" methods that are in the "Network" class.  (Recall that one of the things that the "ClientListener" does is to set variables in the "Network" class when it receives relevant information from the server.  That is the reason why several variables in the "Network" class are "protected".)

After setting up the parent pointer, the "ClientListener" attempts to connect to the server ("connectToServer").  If the attempt fails, the background color of the applet is set to yellow.  Otherwise, a "DataInputStream" and "DataOutputStream" are set up to enable the "ClientListener" to read messages from and send messages to the server.  Do you want to review setting up a client?

The "connectToServer" method attempts to establish a "Socket" with the server.  The client assumes that the server is available on port 41962 (ports range from 0 through 2^16 - 1).

The "sendMessage" method sends a message to the server.  First, the "writeUTF" method is invoked to place the message in the "DataOutputStream".  Then, the "flush" method sends the message to the server.

The "run" method is the most interesting method in the "ClientListener".  The method sits in a "while" loop that continues until a "QUIT" command is issued.  At the top of the loop, the "ClientListener" tries to read a message that has been sent from the server to the client via the "readUTF" command.  If no message is currently available, the "ClientListener" thread sleeps until one becomes available.

One of the most interesting aspects of developing a server/client is deciding upon the communication protocol between the two.  For this Color Belot game, a message begins with a "#" and is then followed by the command.  All commands use upper case letters.  Following the command is another "#".  Any arguments to the command follow this second "#".  The arguments are enclosed by "#" as well.

Once a message is sent, the "determineCommand" method (see below) strips out the command.  The "shortenCommand" method (see below) then removes the leading "#" and the command from the message.  The "shortenCommand" enables arguments to the command to be more easily located.

Let's look at the commands, one at a time.  The commands are processed in alphabetical order.  The first command that is handled is the "CARD" command.  The format of this command is "#CARD#number1#number2#".  The first numeric argument ("whichPosition") specifies where the card image should be displayed and the second numeric argument ("whichCard") specifies which card image to display.  "whichPosition" can take on the values 0 through 10.   Positions 0 through 7 represent the 8 cards in the player's hand.  Position 8 represents the position where the player plays a card ("cardOne").   Position 9 represents the position where the opponent plays a card ("cardTwo").  Position 10 represents the position where the flipped card is placed("cardThree").

The format of the "CARDSTODISPLAY" command is "#CARDSTODISPLAY#number#".  The numeric argument specifies how many cards are currently in the player's hand.  (Recall that there are five cards after the initial deal and eight cards after the secondary deal.)

The format of the "DEALER" command is "#DEALER"number#".   The numeric argument specifies either the player's number or the opponent's number and indicates who has dealt.

The format of the "FIRSTBID" command is "#FIRSTBID#string#".   The string argument can take on the value "Pass" or the name of a trump suit.  This command represents the opponent's first bid.

The format of the "FOLLOWCARD" command is "#FOLLOWCARD#number#".   The numeric argument specifies which card the opponent led.  The card is displayed and then it is the player's turn to follow this lead.

The format of the "GAMEPOINTS" command is "#GAMEPOINTS#number1#number2#".  The first numeric argument specifies how many game points (the points scored for the current game) the player has ("myGamePoints").  The second numeric argument specifies how many game points the opponent has ("yourGamePoints").

The format of the "MESSAGE" command is "#MESSAGE#string#".   The string argument denotes the message that the opponent has sent to the player.   The message is displayed in the "incomingField" "TextArea".

The format of the "PAINT" command is "#PAINT#".  The command causes the client to repaint its screen.

The format of the "PLAYCARD" command is "#PLAYCARD#".  It causes a message to be displayed, requesting the player to click on a card to play it.

The format of the "QUIT" command is "#QUIT#".  It indicates that the other player has quit the game.  An appropriate message is displayed and the outer while loop will be dropped out of.

The format of the "RAWPOINTS" command is "#RAWPOINTS#number1#number2#".  The first numeric argument specifies how many raw points the player has ("myRawPoints").  The second numeric argument specifies how many raw points the opponent has ("yourRawPoints").

The format of the "SECONDBID" command is "#SECONDBID#string#".   The string indicates the opponent's second bid which can either be "Pass" or the name of a trump suit.

The format of the "SLEEP" command is "#SLEEP#".  The command causes the "ClientListener" to sleep for 5 seconds.  This is typically done at the end of one hand to slow things down so that the player has a chance to see the final outcome before a new game begins.

The format of the "STARTBIDDING" command is "#STARTBIDDING#".   Depending on whose turn it is to bid first, an appropriate message is displayed.

The format of the "TOTALPOINTS" command is "#TOTALPOINTS#number1#number2#".  The first numeric argument specifies how many total points (the number of game points accumulated in all games played so far) the player has ("myTotalPoints").  The second numeric argument specifies how many total points the opponent has ("yourTotalPoints").  If one of the players has scored 500 or more points and outscored the other player, the game is finished and the user interface is updated accordingly.

The format of the "TRUMP" command is "#TRUMP#string#".  The string argument specifies what trump is.

The format of the "YOURNUMBER" command is "#YOURNUMBER#number#".   The numeric argument specifies the player's identification number (either 0 or 1).

Take a deep breath - that's all the commands that the "run" method processes!   Can you understand why this information must be conveyed from the server to the client??

The "determineCommand" method takes a message (e.g. "#YOURNUMBER#1#") and returns the string that occurs between the first set of "#" marks.  For this example, it would return "YOURNUMBER".   Do you understand how the method works?

The "shortenCommand" method takes a message (or partial message), such as "#YOURNUMBER#1#" and returns the substring starting with the second "#" symbol.  For this example, "#1#" would be returned.  The method enables messages to be broken up easily to find any command arguments.

Finally, the "ClientListener" uses four instance variables, a "Socket", a "DataInputStream, a "DataOutputStream", and a pointer to the "Network" instance that launches the "ClientListener" in the first place.