CodeGym /Java Blogu /Rastgele /Java RMI'si
John Squirrels
Seviye
San Francisco

Java RMI'si

grupta yayınlandı
MERHABA! Bugün oldukça ilginç bir konuyu ele alacağız: Java RMI. Bu, Uzak Yöntem Çağırma anlamına gelir. Farklı bilgisayarlarda olsalar bile iki programın birbiriyle iletişim kurmasına izin vermek için RMI kullanabilirsiniz. Kulağa havalı mı geliyor? :) Ve bunu yapmak o kadar da zor değil! Bugünün dersinde, RMI etkileşiminin unsurlarını analiz edeceğiz ve onu nasıl yapılandıracağımızı anlayacağız. İhtiyacımız olan ilk şey bir istemci ve bir sunucu. Bilgisayar terminolojisine derinlemesine dalmaya gerçekten ihtiyacımız yok. RMI söz konusu olduğunda, bunlar sadece iki programdır. Bunlardan biri bir nesne içerecek, diğeri ise o nesne üzerinde metotları çağıracaktır. Farklı bir programda var olan bir nesnenin metotlarını çağırma — bu henüz yapmadığımız bir şey! Deneme zamanı! :) Sıkılmamak için, hadi' Programımızı basit tutuyoruz. Genel olarak, bir sunucu, bir istemci tarafından talep edilen bazı hesaplamaları gerçekleştirir. Ve böylece bizimle olacak. Sunucumuz basit bir hesap makinesi programı olacaktır. Yalnızca bir yöntemi olacaktır:çarpma() . İstemci programı tarafından kendisine gönderilen iki sayıyı çarpacak ve ardından sonucu döndürecektir. Her şeyden önce, bir arayüze ihtiyacımız var:

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

public interface Calculator extends Remote {

   int multiply(int x, int y) throws RemoteException;
}
Neden bir arayüze ihtiyacımız var? Çünkü RMI, geçmiş derslerde çalıştığınız proxy'leri oluşturmaya dayanır . Muhtemelen hatırladığınız gibi, proxy'lerle sınıflar üzerinden değil arayüzler üzerinden çalışıyoruz. Arayüzümüz için 2 önemli gereksinim var!
  1. Uzak arayüzü genişletmelidir.
  2. Tüm yöntemleri bir RemoteException atmalıdır (IDE bunu otomatik olarak yapmaz — bunu manuel olarak eklemeniz gerekir!).
Şimdi, Hesap Makinesi arayüzümüzü uygulayan bir sunucu sınıfı oluşturmamız gerekiyor . Uygulamada RMI - 2Burada da her şey oldukça basit:

import java.rmi.RemoteException;

public class RemoteCalculationServer implements Calculator {

   @Override
   public int multiply(int x, int y) throws RemoteException {
       return x*y;
   }

}
Burada aslında yorum yapacak bir şey yok :) Şimdi hesap nesnemizi yapılandıracak ve çalıştıracak bir sunucu programı yazmamız gerekiyor. Bunun gibi görünecek:

import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class ServerMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, AlreadyBoundException, InterruptedException {

       final RemoteCalculationServer server = new RemoteCalculationServer();

       final Registry registry = LocateRegistry.createRegistry(2732);

       Remote stub = UnicastRemoteObject.exportObject(server, 0);
       registry.bind(UNIQUE_BINDING_NAME, stub);

       Thread.sleep(Integer.MAX_VALUE);

   }
}
Bunu çözelim :) İlk satırda, bazı String değişkenlerini bildiriyoruz:

public static final String UNIQUE_BINDING_NAME = "server.calculator";
Bu dize, uzak nesnenin benzersiz adıdır. İstemci programımız, sunucumuzu bulmak için bu adı kullanır: bunu daha sonra göreceksiniz. Ardından, hesap makinesi nesnemizi oluşturuyoruz:

final RemoteCalculationServer server = new RemoteCalculationServer();
Burada her şey açık. Bundan sonrası daha da ilginç:

final Registry registry = LocateRegistry.createRegistry(2732);
Bu Kayıt nesnesi, uzak nesnelerin bir kaydıdır. Bunlar diğer programların uzaktan erişebildiği nesneler :) 2732 sayısını LocateRegistry.createRegistry() yöntemine geçirdik. Bu port numarasıdır — diğer programların nesne kaydımızı bulmak için kullanacağı benzersiz bir numaradır (bunu aşağıda tekrar göreceksiniz). Devam ediyoruz... Bakalım bir sonraki satırda neler olacak:

Remote stub = UnicastRemoteObject.exportObject(server, 0);
Bu satırda bir saplama oluşturuyoruz. Bir saplama, uzak aramanın tamamını kapsar. Bunu RMI'nin en önemli unsuru olarak düşünebilirsiniz. Bu ne işe yarıyor?
  1. Bir yöntemin uzaktan çağrılmasıyla ilgili tüm bilgileri alır.
  2. Yöntemin parametreleri varsa, saplama bunları seri durumdan çıkarır. Bu noktaya dikkat edin! Uzaktan çağrılan yöntemlere ilettiğiniz bağımsız değişkenler seri hale getirilebilir olmalıdır (sonuçta ağ üzerinden iletileceklerdir). Bu bizim için sorun değil - biz sadece sayıları iletiyoruz. Ancak nesneleri iletiyorsanız, bu gerekliliği unutmayın!
  3. Bundan sonra saplama istenen yöntemi çağırır.
Hesap makinesi sunucu nesnemizi UnicastRemoteObject.exportObject() yöntemine aktarıyoruz . Yöntemlerini uzaktan çağırmayı bu şekilde mümkün kılıyoruz. Yapılacak tek bir şey kaldı:

registry.bind(UNIQUE_BINDING_NAME, stub);
Saplamamızı, uzak nesne kayıt defterine en başta oluşturduğumuz adla "kaydederiz". Artık müşteri onu bulabilecek! Belki de programın ana başlığını en sonunda uyku moduna aldığımızı fark etmişsinizdir:

Thread.sleep(Integer.MAX_VALUE);
Sadece sunucunun uzun süre çalışmasına ihtiyacımız var. IDE'de, aynı anda iki main() yöntemini başlatacağız: birincisi, sunucunun main() yöntemi ( daha önce yazmış olduğumuz ServerMain sınıfında) ve ikincisi, istemcinin main() yöntemi ( ClientMain sınıfında, ki aşağıda yazacağız). İstemciyi başlatırken sunucu programının sonlandırılmaması önemlidir, bu nedenle onu uzun bir süre uyku moduna alırız. Her halükarda çalışmaya devam edecek :) Artık sunucumuzun main() metodunu çalıştırabiliriz . Çalıştırmasına izin verin ve istemci programın bir yöntemi çağırmasını bekleyin :) Şimdi istemci programını yazalım! Çarpma için sunucumuza sayıları gönderecek.

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class ClientMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, NotBoundException {

       final Registry registry = LocateRegistry.getRegistry(2732);

       Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);

       int multiplyResult = calculator.multiply(20, 30);

       System.out.println(multiplyResult);
   }
}
Basit görünüyor. Ama burada neler oluyor? İlk olarak, istemci, yöntemlerini uzaktan çağıracağı nesnenin benzersiz adını bilmelidir. Buna göre, istemci programında genel statik nihai String UNIQUE_BINDING_NAME = "server.calculator"; değişken. Ardından, main() yönteminde uzak nesnelerin kaydına erişim elde ederiz. Bunu yapmak için LocateRegistry.getRegistry() yöntemini çağırmamız ve kayıt defterimizi oluşturmak için kullanılan port numarasını ServerMain programında iletmemiz gerekir (port 2732; bu numara sadece bir örnektir - farklı bir numara kullanmayı deneyebilirsiniz):

final Registry registry = LocateRegistry.getRegistry(2732);
Şimdi sadece istenen nesneyi kayıt defterinden almamız gerekiyor! Bu kolaydır, çünkü benzersiz adını biliyoruz!

Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
Tip dökümüne dikkat edin. Alınan nesneyi RemoteCalculationServer sınıfına değil Calculator arayüzüne atıyoruz . Dersin başında söylediğimiz gibi, RMI bir proxy'ye dayanır, bu nedenle uzaktan çağrılar bir sınıfın yöntemleri için değil, yalnızca bir arabirimin yöntemleri için kullanılabilir. Son olarak, nesnemizde multiple() yöntemini uzaktan çağırır ve sonucu konsola veririz.

int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
ServerMain sınıfının main() yöntemi zaten uzun süredir çalışıyor. Şimdi istemci programında ( ClientMain ) main() yöntemini çalıştırmanın zamanı geldi ! Konsol çıktısı:

600
Bu kadar! Programımız (aslında iki program!) yapması gerekeni yaptı :) Zamanınız ve arzunuz varsa, bunu biraz renklendirebilirsiniz. Örneğin, hesap makinesinin dört standart aritmetik işlemi desteklemesini sağlayın ve sayıları ilkel türler olarak değil, CalculationInstance(int x, int y) nesneleri olarak iletin. Bir sonraki derste görüşmek üzere! :)
Yorumlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION