"হাই! এবং আরও একটি আনন্দের বিষয়: RMI। RMI হল রিমোট মেথড ইনভোকেশন । অন্য কথায়, RMI হল এমন একটি মেকানিজম যা একটি জাভা মেশিন থেকে একটি অবজেক্টকে অন্য জাভা মেশিন থেকে অবজেক্টে মেথড কল করার অনুমতি দেয় , এমনকি যদি সেগুলি ভিন্ন হয় কম্পিউটার, বিভিন্ন দেশে, বা পৃথিবীর বিভিন্ন প্রান্তে।"

আরএমআই - 1

"ওহ! এটা অসাধারণ শোনাচ্ছে।"

"হ্যাঁ। কিন্তু আমি শুধুমাত্র আপনাকে একটি সংক্ষিপ্ত বিবরণ দেওয়ার চেষ্টা করব। এটির সাথে, আপনি যদি খুব গভীর খনন করেন, তাহলে এটি কীভাবে কাজ করে তার সূক্ষ্মতা দেখে আপনি বিভ্রান্ত হতে পারেন।"

"কিন্তু আপনি যদি চরম পর্যায়ে না যান, তাহলে RMI শুধুমাত্র খুব সহজ নয়, এটি একজন প্রোগ্রামারের জীবনকে অনেক সহজ করে তোলে। যার জন্য, আমরা এটিকে আমাদের গভীর শ্রদ্ধা জানাই।"

"সুতরাং, আমরা চাই একটি জাভা প্রোগ্রামের একটি অবজেক্ট অন্য জাভা প্রোগ্রামে থাকা একটি অবজেক্টের উপর একটি মেথড কল করতে। এই প্রোগ্রামগুলি যেখানেই চলমান থাকুক না কেন।"

"আসুন সবচেয়ে সহজ উদাহরণটি বিবেচনা করা যাক: যখন উভয় প্রোগ্রাম একই কম্পিউটারে চলছে।  প্রোগ্রামগুলিকে ইন্টারনেটে ইন্টারঅ্যাক্ট করার অনুমতি দেওয়ার জন্য, আপনাকে JVM-এর অনুমতিগুলি কনফিগার করতে হবে , কিন্তু আমরা আজ তা কভার করব না।"

"জাভাতে, আপনি দূরবর্তীভাবে শুধুমাত্র ইন্টারফেসের পদ্ধতিতে কল করতে পারেন, ক্লাস নয়।"

"সুতরাং, আমাদের দুটি প্রোগ্রাম আছে। তারা কিভাবে একে অপরের পদ্ধতি কল করতে পারে?"

"আসুন পরিস্থিতি বিবেচনা করা যাক যেখানে একটি প্রোগ্রামে একটি অবজেক্ট থাকে এবং একটি দ্বিতীয় প্রোগ্রাম সেই বস্তুর উপর মেথড কল করতে চায়। প্রথম প্রোগ্রামটিকে সার্ভার এবং দ্বিতীয়টিকে ক্লায়েন্ট বলি। "

"প্রথমে, আমি কিছু নমুনা কোড প্রদান করব, এবং তারপর আমরা এটি বিশ্লেষণ করব।"

"তাহলে আমাদের প্রোগ্রাম কি করবে?"

"হুম। ওয়েল, সরলতার জন্য, প্রোগ্রামটির একটি পদ্ধতি থাকবে যা এটিতে পাস করা একটি স্ট্রিংকে বিপরীত করে।"

"যথেষ্ট সহজ।"

"আচ্ছা, তাহলে শুরু করা যাক:"

"প্রথম, আমাদের একটি ইন্টারফেস প্রয়োজন যা আমাদের প্রয়োজনীয়তাগুলি পূরণ করবে:"

প্রোগ্রামগুলির মধ্যে যোগাযোগের জন্য ইন্টারফেস
interface Reverse extends Remote
{
 public String reverse(String str) throws RemoteException;
}

"আমি একটি বিপরীত ইন্টারফেস তৈরি করেছি এবং এটিতে একটি রিমোট মার্কার ইন্টারফেস যোগ করেছি, সেইসাথে একটি RemoteException। পদ্ধতিটি কল করার সময় অপ্রত্যাশিত ত্রুটি ঘটতে পারে। যদি কেউ করে থাকে, তাহলে এই ব্যতিক্রমটি নিক্ষেপ করা হবে।"

"এখন আমাদের একটি সার্ভার ক্লাস লিখতে হবে যা এই ইন্টারফেসটি প্রয়োগ করে:"

সার্ভারের জন্য ক্লাস
class ReverseImpl implements Reverse
{
 public String reverse(String str) throws RemoteException
 {
  return new StringBuffer(str).reverse().toString();
 }
}

"আমি দেখছি। আমরা এই পদ্ধতিতে স্ট্রিংকে বিপরীত করি।"

"হ্যাঁ।"

"এখন আমাদের এই অবজেক্টটিকে অন্য প্রোগ্রাম থেকে কলযোগ্য করতে হবে। আপনি এটি কীভাবে করবেন তা এখানে:"

অবজেক্ট শেয়ারিং
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create an object to be accessible remotely.
 final ReverseImpl service = new ReverseImpl();

 // Create a registry of shared objects.
 final Registry registry = LocateRegistry.createRegistry(2099);
 // Create a stub for receiving remote calls.
 Remote stub = UnicastRemoteObject.exportObject(service, 0);
 // Register the stub in the registry.
 registry.bind(UNIC_BINDING_NAME, stub);

 // Put the main thread to sleep, or else the program will exit.
 Thread.sleep(Integer.MAX_VALUE);
}

"আমি এই লাইনটি লাইন দ্বারা ব্যাখ্যা করব।"

" লাইন 1 তে , আমরা UNIC_BINDING_NAME ভেরিয়েবলে  আমাদের দূরবর্তী বস্তুর (যে বস্তুটি দূর থেকে অ্যাক্সেসযোগ্য) জন্য একটি অনন্য নাম (যা আমরা তৈরি করেছি) সংরক্ষণ করি৷ যদি প্রোগ্রামটি বেশ কয়েকটি অবজেক্টকে অ্যাক্সেসযোগ্য করে তোলে তবে প্রত্যেকটির নিজস্ব অনন্য নাম থাকতে হবে৷ আমাদের বস্তুর অনন্য নাম 'server.reverse'।"

" লাইন 6-এ আমরা একটি ReverseImpl অবজেক্ট তৈরি করি যা দূর থেকে অ্যাক্সেসযোগ্য হবে। এর পদ্ধতিগুলিকে আহ্বান করা হবে।"

" লাইন 9-এ আমরা একটি বিশেষ বস্তু তৈরি করি যাকে একটি রেজিস্ট্রি বলা হয়। আমাদের শেয়ার করা বস্তুগুলিকে নিবন্ধন করতে এটি ব্যবহার করতে হবে। JVM পরে তাদের সাথে যোগাযোগ করবে। 2099 হল একটি পোর্ট (একটি অনন্য নম্বর যা অন্য একটি প্রোগ্রাম আমাদের অ্যাক্সেস করতে ব্যবহার করতে পারে। অবজেক্ট রেজিস্ট্রি)।"

"অন্য কথায়, একটি অবজেক্ট অ্যাক্সেস করার জন্য, আপনাকে অবজেক্ট রেজিস্ট্রির অনন্য নম্বর (পোর্ট) এবং অবজেক্টের অনন্য নাম জানতে হবে এবং দূরবর্তী বস্তু দ্বারা প্রয়োগ করা ইন্টারফেসের মতো একই ইন্টারফেস থাকতে হবে।"

"আমি দেখছি। এরকম কিছু: ফোনে কল করুন (একটি নম্বর প্রয়োজন) এবং বিলের জন্য জিজ্ঞাসা করুন (একটি বস্তুর নাম)?"

"হ্যাঁ। এখন, চলুন চালিয়ে যাই।"

" 11 লাইনে  , আমরা একটি স্টাব তৈরি করি৷ একটি স্টাব হল একটি বিশেষ বস্তু যা দূরবর্তী কল সম্পর্কে তথ্য গ্রহণ করে, এটিকে আনপ্যাক করে, পদ্ধতির আর্গুমেন্টগুলিকে ডিসিরিয়ালাইজ করে এবং প্রয়োজনীয় পদ্ধতিটিকে কল করে৷ তারপর এটি ফলাফল বা ব্যতিক্রমকে সিরিয়ালাইজ করে, যদি একটি ছিল , এবং এটি সমস্ত কলারকে ফেরত পাঠায়।"

"আমি দেখতে পাচ্ছি। প্রায়। আপনি বলেছিলেন যে এটি 'পদ্ধতি আর্গুমেন্টগুলিকে ডিসিরিয়ালাইজ করে'। তাই, এর মানে রিমোট পদ্ধতির আর্গুমেন্টগুলি অবশ্যই সিরিয়ালাইজেবল হতে হবে?"

"হ্যাঁ। আপনি কীভাবে তাদের নেটওয়ার্কের মাধ্যমে পাঠাবেন? সত্য, ব্যতিক্রম আছে, যেমন বস্তু যেগুলি রেফারেন্স দ্বারা পাস করা হয়, কিন্তু আমরা আজ সেগুলি সম্পর্কে কথা বলব না।"

"আমরা এটিকে এভাবে রাখব: আপনি অ-ক্রমিক বস্তুগুলি পাস করতে পারবেন না, তবে আপনি যদি সত্যিই চান তবে আপনি করতে পারেন। তবে এটি একটি যন্ত্রণা, আপনি জানেন।"

"ঠিক আছে."

"তাহলে চলুন চালিয়ে যাওয়া যাক।"

" 13 লাইনে , আমরা আমাদের বস্তুর স্টাবটিকে রেজিস্ট্রিতে একটি অনন্য নামে নিবন্ধন করি।"

" লাইন 16 তে , আমরা মূল থ্রেডটি ঘুমাতে রাখি। সমস্ত দূরবর্তী কলগুলি পৃথক থ্রেডে প্রক্রিয়া করা হয়। গুরুত্বপূর্ণ বিষয় হল প্রোগ্রামটি চলছে। তাই আমরা কেবল এখানে মূল থ্রেডটিকে ঘুমাতে রাখি। এটাই।"

"ঠিক আছে."

"দারুণ, তাহলে এখানে একটি ক্লায়েন্টের উদাহরণ:"

দূরবর্তী বস্তুর সাথে কাজ করা
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create a registry of shared objects
 final Registry registry = LocateRegistry.createRegistry(2099);

 // Get the object (actually, this is a proxy object)
 Reverse service = (Reverse) registry.lookup(UNIC_BINDING_NAME);

 // Call the remote method
 String result = service.reverse("Home sweet home.");
}

"আমি এই কোড লাইনটি লাইন দ্বারা ব্যাখ্যা করব:"

" লাইন 1  হল দূরবর্তী বস্তুর অনন্য নাম । এটি ক্লায়েন্ট এবং সার্ভার উভয় ক্ষেত্রেই একই হতে হবে।"

" লাইন 6 এ  , আমরা একটি « দূরবর্তী বস্তুর রেজিস্ট্রি » তৈরি করি। এর পোর্ট (2099) সার্ভার অ্যাপ্লিকেশনের জন্য রেজিস্ট্রির পোর্টের মতোই হতে হবে।"

" 9 লাইনে , আমরা রেজিস্ট্রি থেকে অবজেক্টটি পাই । প্রত্যাবর্তিত বস্তুটি একটি প্রক্সি অবজেক্ট এবং একটি ইন্টারফেসে রূপান্তরিত হয়। ইন্টারফেসটি অবশ্যই রিমোট মার্কার ইন্টারফেসের উত্তরাধিকারী হবে।"

" লাইন 12 তে , আমরা ইন্টারফেসের পদ্ধতিগুলিকে কল করি যেন বস্তুটি একই প্রোগ্রামের মধ্যে তৈরি করা হয়েছিল৷ কোনও পার্থক্য নেই৷"

"কুল! এখন আমি বিতরণ করা অ্যাপ্লিকেশন লিখতে পারি। বা অ্যান্ড্রয়েডের জন্য ব্যাটলশিপের মতো গেমস।"

"আপনি কি সাহস করবেন না, অ্যামিগো! 27 শতকে অ্যান্ড্রয়েড অপারেটিং সিস্টেমটি বিশ্ব দখল করার তৃতীয় প্রচেষ্টার পরে নিষিদ্ধ করা হয়েছিল। রোবটদের এটিতে কোনও অ্যাক্সেস নেই। এটি থেকে আপনাকে দূরে সরিয়ে নেওয়ার কোনও উপায় থাকবে না আপনি চিৎকার করে দৌড়াতে শুরু করবেন, "সব মানুষকে মেরে ফেল!""

"হুম। ঠিক আছে। কিন্তু আমাকে এখনও ডিয়েগোকে জিজ্ঞাসা করতে হবে। আপনি কখনই জানেন না, হয়তো তার কাছে এটি সম্পর্কে কিছু আকর্ষণীয় বলার আছে।"

"তাহলে তাকে জিজ্ঞেস কর। ঠিক আছে, ঠিক আছে, আগামীকাল পর্যন্ত।"

"বাই, ঋষি। আকর্ষণীয় পাঠের জন্য ধন্যবাদ।"