# problem with RMI betserver programming task



## Zimt1147 (10. Nov 2003)

Hallo zusammen,

ich habe ein kleines Problem mit einer Programmieraufgabe, hier ist die Aufgabenstellung:

"You are required to implement a distributed betting system, in which a set of users, or punters, place bets concerning the outcome of a draw comprising a random choice of one number from a set of 20 numbers (numbers 0 to 19). 

The users communicate with the bookmaker, the system that coordinates the bets, that is, receives subscriptions from clients who wish to participate in the betting system, receives bets from registered clients and returns the current state of the betting (the numbers on which bets have already been placed). At regular intervals (by default, every 5 minutes), the bookmaker randomly selects a winning number and informs all the clients of the result. 

The bookmaker executes a periodic thread every few minutes (the time interval being set in the system initialization) to carry out the draw, that is, to select the winning number. Before doing so, when the time alloted for placing bets has expired, the bookmaker sends the final state of the betting to all the registered clients and accepts no further bets. Once the winning number has been chosen, the bookmaker sends this information to all the registered clients.

A complete solution should use synchronisation mechanisms to ensure that the remote object is threadsafe, that is, to ensure the integrity of the data describing the current state of betting
"


Also, ich kann die Dateien kompilieren, allerdings weist das Programm einige Fehler auf:
wenn ich den Security-manager nicht auskommentiert haette, wuerde es abstuerzen,
desweiteren passiert bei einer Eingabe von 1,2 oder 3 nichts.
Fuer Anregungen oder Hilfen jeder Art bin ich dankbar, den Quelltext habe ich unten geposted!

Gruss
Alex


///////////////////////////////////////////////////////////////////




```
/*
* BookieImpl.java
*
*/

import java.net.*;
import java.io.*;
import java.util.*; // for the method random() and for the Vector Class which stores clients

import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*; // to make the registry in order to localise remote objects
import java.lang.* ; // for the Security Manager


public class BookieImpl extends UnicastRemoteObject implements BookieInterface{


// private attributes and instanciations
private static final int REGISTRY_PORT = 10005;
private static BookieImpl betting_server; //instance of the betting server
private int [] state_bets = new int [20]; //array which stores of the bets of the clients
private static int last_client = 999;
protected Vector list_clients; // array of all the clients registered
private static int bets_possible = 1; // 1 = possible, 0= bets finished
private int intervalle = 300; // by default, the random time is 5 minutes
private counter c;

// methods and constructor

public BookieImpl() throws RemoteException {
// constructor: initiate the array of the bets

for (int i=0; i<20; ++i)
state_bets = -1;
// also set the random value default

// create the array witch will store al registered clients.
list_clients = new Vector ();

// Launch the counter
c = new counter();

System.out.println("Initialization done. The bets are open.\n");
}

public int register(PunterInterface client) throws RemoteException {

// returns user_id of the client which asks registration
list_clients.addElement (client); //store new client registered
last_client ++; // incremente the number of the client
System.out.println("new client registered with id. : " + last_client + "\n");
return last_client;
}

public void deregister(PunterInterface client, int num_client) throws RemoteException {
list_clients.removeElement (client);
for (int i=0; i<20; ++i){
if (state_bets==num_client) {state_bets=-1;}
}
}

public int[] consult_bets() throws RemoteException {
// returns array with the user_id of each number beaten (or -1 if number free)
return state_bets;
}


public boolean bet(int num, int user_id) throws RemoteException {
// valid or not (clients exists, number already chosen, bet_possible)
if ((state_bets[num]==-1) && (user_id>=1000) && (user_id<=last_client) && (bets_possible==1))
{
state_bets[num]=user_id;
System.out.println ("New bet done by user "+ user_id + " on the number " + num + "\n");
return true;
}
else
return false;
}

public void draw_number() throws RemoteException { //static removed...

bets_possible = 0;
int draw = (int) Math.random()*20+1;
System.out.println ("Time is over. The number drawn is : 2 "+ draw + "\n");


Vector list_clients = (Vector) this.list_clients.clone();
for (int i = 0; i < list_clients.size(); ++ i) {
PunterInterface client = (PunterInterface) list_clients.elementAt(i);
try {
client.send_final_state(state_bets);
client.send_draw_result(draw,state_bets[draw]); 
}
catch (RemoteException ex) { this.list_clients.removeElement(client); }
}

// reset the state of betting
for (int j=0; j<20; ++j)
{state_bets[j]=-1;}

System.out.println("Continue the storing of bets? (Y or N)");
try {
BufferedReader entry=new BufferedReader (new InputStreamReader (System.in));
String msg = entry.readLine();
if (msg.equals("Y")) {bets_possible = 1;}
else {
c.stop();
System.out.println("the bets will stop\n");
}
}
catch (IOException e) {}

}
public static void main (String[] args) throws Exception {

//Security manager to permit class_downloading (remotely downloading)
// needed if we don't copy classes in the stub client
/*
if (System.getSecurityManager()==null) {
System.setSecurityManager(new RMISecurityManager());
}
doesn'T work, crashes on startup!!
*/


try {
System.out.println("Start of the bets : 300 sec. left until the end of bets \n");
// Create remote object, publish it in the registry, etc.
betting_server = new BookieImpl() ;
// Registers the object with the Naming Service / in the registry
Registry registry = LocateRegistry.createRegistry(REGISTRY_PORT);
registry.rebind ("server name", betting_server);
}
//catch (MalformedURLException mURLe){
// System.out.println("wrong syntax of URL with : " + mURLe);
// }
//there is no way this can be thrown!

catch (java.rmi.UnknownHostException uhe){
System.out.println("Host " + "host name" + " not found");
}
catch (RemoteException re){
System.out.println("Error during the RMICal of " + re);
}


}


}




////////////////////////////////////////////////////////////////
/*
* counter.java
*
*/



import java.net.*;
import java.io.*;
import java.util.*; // for the method random() and for the Vector Class which stores clients

import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*; // to make the registry in order to localise remote objects


public class counter extends Thread {

public int delay;
public BookieImpl book;

public void counter() {
this.delay = 300;
// if we want to change this value which will be 5 min by default, we have to add a parameter time in the constructor and initiliase it at the call of the constructor.
//Hier hab ich nen try/catcch eingef?gt...
try {
book = new BookieImpl();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


this.start(); // call the run() method
}

public void run(){
try {
System.out.println("counter launched\n");
for (int i=0;i<5;i++) {

sleep(this.delay * 1000);
book.draw_number() ;

}
}
catch (InterruptedException exc) {
exc.printStackTrace();
// for the sleep
}
catch (SecurityException se) {}
//Eingef?gt da es fehlte
catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // when we stop the thread
}


}


/////////////////////////////////////////////////////////
/*
* PunterInteraction.java
*
*/

//package RMI.CLIENT;


//import java.net.*;
import java.io.*;
import java.util.*; // for the method random() and for the Vector Class which stores clients
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*; // to make the registry in order to localise remote objects
import java.awt.event.*;

public class PunterInteraction extends Thread {



public boolean quit = false;
PunterInterface p;
//void deleted
public PunterInteraction(PunterInterface p) {
this.p=p;
this.start();
}


public void run() {
try {
BufferedReader entry = new BufferedReader(new InputStreamReader (System.in));
while (!quit) {
System.out.println("Welcome. You can choose to : \n 1. Make a bet (type 1 followed by the number of the bet (0 to 19) \n 2. See the state of the current bets \n 3. Quit the betting process.\n What do you want?\n");
String msg = entry.readLine();
if (msg.equals("3")){quit=true;}
try {
this.p.said(msg); }
catch (RemoteException e) { }

}
}
catch (IOException e) {}
}




}


////////////////////////////////////////////////////////////////////////


/*
* Punter.java
*
*/

//package RMI.CLIENT;

import java.awt.event.*;
import java.io.*;
import java.util.*; // for the method random() and for the Vector Class which stores clients

import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*; // to make the registry in order to localise remote objects


public class Punter extends UnicastRemoteObject implements PunterInterface{
protected static int user_id;
protected static int [] state = new int[20];
private static final int REGISTRY_PORT = 10005;
private final static String HOST_NAME = "server name";
protected static BookieInterface server;

/** Creates a new instance of Punter */
public Punter() throws RemoteException{
System.out.println("constructor of the client : new client. We are going to process to a registration\n");
}

public void send_final_state (int [] final_state) throws RemoteException{
System.out.println ("bets are finished. Here is the final state :\n");
for (int i=0; i<= 19; ++i)
{ // we store the results :
state = final_state;
if (final_state != -1)
// Display this information to the user
{System.out.println("The number " + i + " has been chosen by the user of id. : " + final_state + "\n");
}
}
}

public void send_draw_result (int draw_result, int winner) throws RemoteException {
System.out.println("the bookmaker drew a number : " + draw_result +"\n");
if (this.user_id == winner)
System.out.println("you won\n");
}


public void said (String msg) {
try {
if (msg.charAt(0)=='2') {
int []state_bet = server.consult_bets();
for (int i=0; i<20; ++i)
{System.out.println(i+" : "+state_bet+" |");}
}

if (msg.charAt(0)=='1') {
String bet_string = msg.substring(1);

int bet_num = Integer.valueOf(bet_string).intValue();


boolean result = server.bet(bet_num,this.user_id);
if (result) {System.out.println("You bet has been accepted\n");}
else {System.out.println("Wrong bet or wrong identifier\n"); }

}

if (msg.charAt(0)=='3') {
PunterInterface c= (PunterInterface) this;
server.deregister(c,user_id); 
System.out.println("You have chosen to deregister\n");
} 

}

catch (RemoteException ex) {
//ex.printstackTrace();
}

catch (ArrayIndexOutOfBoundsException ae){}


}


public static void main(String[] args) throws Exception {

try {
System.out.println("Start of the client\n");
// Create instance of itself as remote object
Punter client = new Punter ();
// We have to declare the object has an interface beacause it will be passed in argument

PunterInterface c = (PunterInterface) client;

// Obtain acces to the bookmaker server
if (server == null){

// Get access to the remote object (server)
Registry registry = LocateRegistry.getRegistry(REGISTRY_PORT);
server = (BookieInterface) registry.lookup (HOST_NAME);
//register the object

client.user_id = server.register(c);
System.out.println("You have been registered with the id. : "+ client.user_id + "\n");


// Start an interaction process waiting for instructions and sending them
// on to the bookmaker server
PunterInteraction pt = new PunterInteraction(c);
}
}
catch (Exception re) {
System.out.println("" + re);
}


}




}



/////////////////////////////////////////////////////////////




/*
* BookieInterface.java
*
*/

//package RMI.SERVER;


import java.rmi.Remote;
import java.rmi.RemoteException;

public interface BookieInterface extends Remote{

public abstract int register(PunterInterface client) throws RemoteException;
// enables or not the registration of the client. returns the user_id
//public abstract void deregister(PunterInterface client, int num_client) throws RemoteException;
// remotes the client who want a deregistration
public abstract int[] consult_bets() throws RemoteException;
// returns array of state (for each number : user_id or -1 if no bets)
public abstract boolean bet(int num, int user_id) throws RemoteException;
// enables a client to make a bet. return : says if the bets is valid or not
public abstract void draw_number() throws RemoteException;

public abstract void deregister(PunterInterface c, int user_id) throws RemoteException;
// missing before...

}




////////////////////////////////////////////////////////


/*
* PunterInterface.java
*
*/

//package RMI.CLIENT;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.awt.event.*;


public interface PunterInterface extends Remote{
public abstract void send_final_state(int[] final_state) throws RemoteException;
public abstract void send_draw_result (int draw_result, int winner) throws RemoteException;
// public abstract void start() throws RemoteException;
public abstract void said(String msg)throws RemoteException ; 





}
```
[/code]


----------



## gustav (11. Nov 2003)

Will mich jetzt nicht detailiert in Deinem Programmcode vergraben !

Welche Ausgaben erhältst Du ? Wird der Server richtig gestartet ? Wird die Registry ordentlich erkannt ? 
Wenn Du hinter einer Firewall bist, die den StdPort 1099 blockiert kann nichts passieren. Allerdings verständigen sich der Client und der Server intern auch mal andere Ports zu nutzen. Dann passiert auch wieder nichts. RMI ist eine sehr feinfühlige Sache (meine Erfahrung) selbst mit korrekten Programmen kann die Fehlersuche recht lange dauern. Deshalb teste erst ab, ob alles wirklich korrekt funktioniert.

Fang am besten nur mal mit einem Server an, der das gute alte Hello World Problem löst :

```
/* gemeinsames Interface für Client und Server */

import java.rmi.* ;

public interface TRMIinterface extends Remote 
{
    // Object executeTask(Task t) throws RemoteException ;
    public int ServerRoutine1() throws RemoteException ;
}

// ###############################################


import java.rmi.* ;
import java.rmi.server.* ;

public class TRMIServer extends UnicastRemoteObject implements TRMIinterface
{
  private int CallCounter ;   /* zählt die Funktionsaufrufe durch die Clients */

  public TRMIServer() throws RemoteException
  {
    super() ;

    CallCounter = 0 ;
  }

   public int ServerRoutine1() throws RemoteException
   {
     try
     {
       System.out.println("Anfrage von " +getClientHost()
                         +" Antwort :" +( ++CallCounter)) ;
     } catch (ServerNotActiveException e) {}

     return CallCounter ;
   }
}

// ######################################################

	import java.rmi.* ;
import java.rmi.server.* ;

import java.util.Properties ;
import java.net.* ;


public class myClient
{
   public static void main(String args[])
   {

     String RMIServerName = "HelloServer/";

    /* ------------------------------------------------------------------ */
    /* Verbindung zum Server aufnehmen                                    */
    /* ------------------------------------------------------------------ */
     try
     {
	TRMIinterface dataObj = (TRMIinterface) Naming.lookup( RMIServerName) ;
	
	int back = dataObj.ServerRoutine1() ;
	
	
	System.out.println("Client Meldung : Server liefert "+back) ;
	System.out.flush() ;
	
	dataObj.ExecuteClass( CodeBase, Codename) ;
     }
     catch (Exception e) 
       {
         System.out.println("RMI Client meldet : Fehler aufgetreten..") ;
	 System.out.println("RMI Server :" +RMIServerName) ;
	 System.out.flush() ;
         e.printStackTrace() ; 
       }
       
   }
}

// #########################################################

/* TestSM = TestServerMachine */

import java.rmi.Naming ;
import java.rmi.RemoteException ;
import java.rmi.RMISecurityManager ;
// import java.rmi.server.UnicastRemoteObject ;
import java.rmi.registry.LocateRegistry ;
import java.util.Properties ;

/* für die Exceptions */
import java.net.* ;
import java.rmi.* ;

public class TestSM 
{   
 
 /* 
  * MAIN startet nur den Server und installiert den ben"otigten 
  * Security Manager 
  */
 
   /* 2 Parameter die durch Laden aus server.def gesetzt werden  */
   private static String HOST_NAME   = "localhost";
   private static String PORT_NUM = "1099" ;
   private static String SERVER_NAME = "HelloServer/" ;

 

/* ------------------------------------------------------------------------- */
   public static void main(String args[])
   {
     System.out.println("versuche SecurityManager zu installieren....") ;
      
     // Create and install a security manager
     if (System.getSecurityManager() == null) 
     {
	System.setSecurityManager(new RMISecurityManager()) ;
     }
     
     System.out.println("SecurityManager intalliert....") ;
     

    /* ------------------------------------------------------------------ */
    /* Eventuelle Einstellungen aus ini File holen                        */
    /* ------------------------------------------------------------------ */
     TConfigFileHandler Conf = new TConfigFileHandler() ;
     Conf.Load("server.def") ;

     Properties p = System.getProperties() ;
//     p.setProperty("java.rmi.server.logClass", true) ;

     HOST_NAME = p.getProperty("my.TConfigFileHandler.ServerHostName") ;
     PORT_NUM = p.getProperty("my.TConfigFileHandler.ServerPort") ;
     SERVER_NAME = p.getProperty("my.TConfigFileHandler.ServerName") ;
     
     int portNum = 0 ;

     try
     {
       portNum = Integer.parseInt(PORT_NUM) ;
     } 
     catch (Exception e) 
     { 
       System.out.println("Fehler bei der PortNummer") ;
       System.out.flush() ;
     }

    System.out.println("versuche RMI Registry zu initialisieren....") ;
   /* -------------  Registry laden  ---------------------- */
     try
     {
       LocateRegistry.createRegistry( portNum ) ;
       System.out.println( "Registry created on host computer " + 
	                     HOST_NAME + " on port " +PORT_NUM ) ;
     }
     catch (RemoteException e) 
     { 
       System.out.println("!!!! Fehler beim Erstellen der Registry !!!!!\n") ;
       System.out.flush() ;
//       System.out.println(e.getMessage()) ;
//       e.printStackTrace() ;
     }
     finally { }

  /* ---------------- Serverobjekt erstellen ---------------------------- */

     /* Namen für den RMI Server generieren */
     String urlString = "rmi://" 
                         + HOST_NAME + ":" 
			 + PORT_NUM + "/" 
			 + SERVER_NAME ;

     System.out.println("versuche Server zu starten....|"+urlString +"|") ;
      
     TRMIServer obj = null ; 
     try 
     {
        /* Server wird automatisch als (Daemon?)Thread gestartet */
       obj = new TRMIServer() ;
       System.out.println("Server created") ;       
     }
     catch (RemoteException e)
     {
       obj = null ;
       System.out.println("Server Objekt konnte nicht erzeugt werden !") ;
       System.out.println(e.getMessage() ) ;
     }
     finally {  }
	
  
   /* -------- versuche Server an die Registry zu binden ------------------ */
   
     int Fehler = 0 ;
     
     if (obj != null)
     {
       try
       {
          // Bind this object instance to the name "HelloServer"
	  Naming.bind(urlString, obj);
          System.out.println("Server bound in registry") ;	  
       } 
       catch (AlreadyBoundException e) 
       {
	  System.out.println("Server bereits vorhanden : " + e.getMessage()) ;
	  Fehler++ ;
       }
       catch (MalformedURLException e2)
       {
          System.out.println("Fehler in URL Adresse") ;
	  Fehler++ ;
       }
       catch (RemoteException e3)
       {
          System.out.println("Registry konnte nicht gefunden werden") ;
	  Fehler++ ;
       }
       finally { } 
           
       System.out.println("Server active :") ;
     } // obj != null
     
     
     /* Fehler aufgetreten ? */
     if (Fehler != 0) 
     {
        try { obj.ShutDown() ; }
	catch (Exception e) {}
     }

   }
}
```


----------



## ylpqxmw gdyst (20. Mrz 2008)

ahzwbd cpzh iqowp nrvixc nwijpstk gvhkqdx mywholdkt


----------

