fel
le

RPC kliens-szerver ZH

Készítsünk RPC alapú kliens-szervert, amely egy banki utalási rendszert szimulál. A szerver az alábbi funkciókat valósítja meg:

  • peldanyKeszit(): példányosít és aktivál egy egy többfunkciós szerver objektumot a szerver oldalon, amely kötődik a klienshez. A funkciókat lásd lejjebb.

A kliens-aktivált objektum függvényei:

  • login(user,pwd): a felhasználó loginol. Az egyszerűség kedvéért minden logint elfogadunk, az adott user account automatikusan létrejön. A jelszó tárolásra kerül. Legközelebb már csak ugyanezzel a jelszóval lehet erre a usernévre loginolni. A fv bool értékkel tér vissza, hogy sikerült-e a login vagy sem.

Az alábbi függvények csak login után vehetők igénybe:

  • logout(): értelemszerű
  • feltölt( pénz ): a user feltölti a számlaegyenlegét, az adott mennyiségű pénz hozzáadódik a jelenlegi pénzmennyiségéhez.
  • lekérdez(): megadja az aktuális egyenleget,
  • utal( célUser, pénz ): átutal adott összegű pénzt az egyenlegről az adott user-nek. A céluser accountnak léteznie kell, és a számlán megfelelő mennyiségű pénznek léteznie kell.
  • utalások(): string lista, megadja hogy kinek és mennyi pénzt utaltunk át korábban, és mikor történt az utalás (időpont)

Készítsen szervert, mely tetszőlegesen sok konkurrens logint kezel, kiszolgál több klienst is. Készítsen egyszerű klienst, ahol egysoros parancsokat tudunk beküldeni, és a szerver választ kiértékelni, hasonlóan mint a stream kliens esetén, pl "LOGIN|zozó|mazsola123" a login esetén. A kliens az egysoros bevitelű parancsot RPC hívássá alakítja, és átküldi a szerver felé.

Az RPC interface DLL

public interface IPeldanyosit
{
  string peldanyKeszit();
}

public interface IBankiRendszer
{
   bool bejelentkezes(string nev,string jelszo);
   void logout();
   void feltolt(double penz);
   void lekerdez();
   void utal(string celuser, double penz);
   List<string> utalasok();
}
 

Az RPC szerver példányosító osztálya

class Peldanyosito: IPeldanyosit
{
   public string peldanyKeszit()
   {
      string id= Guid.NewGuid().ToString();
      RemotingConfiguration.RegisterWellKnownServiceType(
         typeof( BankiKomm ) ,
         id ,
         WellKnownObjectMode.Singleton
      ) ;
      return id ;    
   }
}
 

Az RPC szerver segédosztályai

class utalas
{
   public DateTime idopont;
   public int osszeg;
   public string celSzemely;
   public utalas(int osszeg, string celSzemely)
   {
       this.idopont = DateTime.Now;
       this.osszeg = osszeg;
       this.celSzemely = celSzemely;
   }
}

class user
{
   public string login;
   public string passwd;
   public int egyenleg;
   public List<utalas> utalasok = new List<utalas>();
 
   public user(string login, string passwd)
   {
      this.login = login;
      this.passwd = passwd;
   }
}
 

Az RPC szerver segédosztályai

class BankiKomm : IBankiRendszer
{
  public static List<user> userek = new List<user>();
  public user logged_in = null;

  protected user kereses(string loginNev)
  {
     lock(userek)
     {
       foreach(user k in userek)
       {
         if (k.login == nev)
         return k;
       }
     }
     return null;
  }
       
  public bool bejelentkezes(string nev, string jelszo)
  {
    user p = kereses(nev);
    if (p==null) // nincs rajta listan
    {
      lock(userek)
      {
        p = new user( nev, jelszo, 0 );
        userek.Add( p );
      }
      logged_in = p;
    }
    else
    {
      // es tudja a jelszot is
      if (p.passwd==jelszo) logged_in = p;
      // else nem tudja a sajat jelszavat
    }
    if (this.logged_in==null) return false;
    else return true;
  }

  public void logout()
  {
    this.logged_in = null;
  }
       
  public int lekerdez()
  {
     if (this.logged_in == null)
        throw new Exception("Logolj be");
     return this.logged_in.egyenleg;        
  }
       
  public void utal(string celuser, int penz)
  {
    if (this.logged_in == null)
       throw new Exception("Logolj be");
    if (this.egyenleg<penz)
       throw new Exception("nincs ennyi penzed");
    user c = kereses(celuser);
    if (c==null)
       throw new Exception("cel user ismeretlen");
               
    lock(c)
    {
       c.egyenleg = c.egyenleg + penz;
    }
    lock(this.logged_in)
    {
       this.logged_in.egyenleg = this.logged_in.egyenleg - penz;
       utalas log = new utalas(celuser, penz);
       this.logged_in.utalasok.Add( log );
    }
  }      
 
  public List<String> utalasok()
  {
    if (this.logged_in == null)
       throw new Exception("Logolj be");
    List<String> ret = new List<String>();
    lock(this.logged_in)
    {
        foreach(utalas u in this.logged_in.utalasok)
        {
           String s = String.Format("{0}|{1}|{2} Ft",u.celSzemely,u.idopont,u.osszeg);
           ret.Add( s );
        }
    }
    return ret;
  }
 

Az RPC Szerver főprogram

class Program
{
  static int port = 8085;
  static void Main(string[] args)
  {
       TcpChannel chan = new TcpChannel( port );
       ChannelServices.RegisterChannel(chan, false);
       RemotingConfiguration.RegisterWellKnownServiceType(
          typeof(Peldanyosito),
          "Peldanyosito",
          WellKnownObjectMode.Singleton);
       Console.WriteLine("A szerver elindult");
       Console.ReadLine();
  }
}
 
Hernyák Zoltán
2013-04-24 19:52:22