Server ActivitiesThe processing done by the server is illustrated in Figures Figure 32-6, 32-7, and 32-8, and is of two types:
BroadcastingThe most complex broadcasting is triggered by the arrival of a create message at the server. Figure 32-6 shows how create fits into the overall activity of creating a new sprite. Figure 32-9 expands the "broadcast create and request for details" box in the server swimlane in Figure 32-6. Figure 32-9. Server activities for a create messageTourServerHandler is principally concerned with differentiating between the messages it receives. TourGroup handles the two modes of client communication: broadcasting or client-to-client. TourGroup maintains an ArrayList of TouristInfo objects, which contain the output streams going to the clients. When a create n x z message arrives at the TourServerHandler, it's passed to doRequest( ), which decides how to process it (by calling sendCreate( )): private void doRequest(String line, PrintWriter out) { if (line.startsWith("create")) sendCreate(line); else if (line.startsWith("detailsFor")) sendDetails(line); else // use TourGroup object to broadcast the message tg.broadcast(cliAddr, port, userName + " " + line); } sendCreate( ) extracts the sprite's name from the message and stores it for later use. It then uses the TourGroup object to broadcast wantDetails and create messages to the other clients: private void sendCreate(String line) { StringTokenizer st = new StringTokenizer(line); st.nextToken( ); // skip 'create' word userName = st.nextToken( ); // userName is a global String xPosn = st.nextToken( ); // don't parse String zPosn = st.nextToken( ); // don't parse // request details from other clients tg.broadcast(cliAddr, port, "wantDetails " + cliAddr + " " + port); // tell other clients about the new one tg.broadcast(cliAddr,port,"create "+userName +" "+xPosn+" "+zPosn); } The broadcast( ) method in TourGroup iterates through its TouristInfo objects and sends the message to all of them, except the client that transmitted the message originally: synchronized public void broadcast(String cliAddr, int port, String msg) { TouristInfo c; for(int i=0; i < tourPeople.size( ); i++) { c = (TouristInfo) tourPeople.get(i); if (!c.matches(cliAddr, port)) c.sendMessage(msg); } } All the methods in TourGroup are synchronized since the same TourGroup object is shared between all the TourServerHandler tHReads. The synchronization prevents a TouristInfo object being affected by more than one thread at a time. sendMessage( ) in TouristInfo places the message on the output stream going to its client: public void sendMessage(String msg) { out.println(msg); } Client-to-Client Message PassingClient-to-client message passing is only used to deliver a detailsFor message to a client. Figure 32-6 shows how detailsFor fits into the overall activity of creating a new sprite. Figure 32-10 expands the "send sprite details for client n1 to client at (A, P)" box in the server swimlane in Figure 32-6. Figure 32-10. Server activities for a detailsFor messageThe TourServerHandler processes the message in doRequest( ), as shown in the previous section, and calls sendDetails( ): private void sendDetails(String line) { StringTokenizer st = new StringTokenizer(line); st.nextToken( ); // skip 'detailsFor' word String toAddr = st.nextToken( ); int toPort = Integer.parseInt( st.nextToken( ) ); String xPosn = st.nextToken( ); // don't parse String zPosn = st.nextToken( ); // don't parse String rotRadians = st.nextToken( ); // don't parse tg.sendTo(toAddr, toPort, "detailsFor " + userName + " " + xPosn + " " + zPosn + " " + rotRadians); } sendDetails( ) passes the message to TourGroup's sendTo( ) method. However, the client's IP address and port number are extracted first to "aim" the message at the correct recipient. The name of the sprite (userName) is added to the message, obtained from a global in TourServerHandler. TourGroup's sendTo( ) cycles through its ArrayList of TouristInfo objects until it finds the right client and sends the message: synchronized public void sendTo(String cliAddr,int port,String msg) { TouristInfo c; for(int i=0; i < tourPeople.size( ); i++) { c = (TouristInfo) tourPeople.get(i); if (c.matches(cliAddr, port)) { c.sendMessage(msg); break; } } } |