Ngôn ngữ lập trình Java do công ty Sun Microsystems phát triển vào đầu thập kỷ 1990. Trải qua hơn 20 năm phát triển, Java thật sự đã lớn mạnh. Hiện tại, Java đã có mặt trong hầu hết các lĩnh vực lập trình với các tên gọi quen thuộc như Java.net, RMI, JDBC, JSP, Servlet, Java Mail, J2ME…
Trang 1MỤC LỤC
Danh mục hình ảnh 7
Danh mục từ viết tắt 9
PHẦN I: TÌM HIỂU KỸ THUẬT LẬP TRÌNH PHÂN TÁN TRONG JAVA Chương 1: TỔNG QUAN VỀ LẬP TRÌNH PHÂN TÁN 11
1.1 Lập trình phân tán là gì? 11
1.2 Vấn đề gọi phương thức từ xa 12
1.3 Lập trình phân tán với Java 12
Chương 2: LẬP TRÌNH PHÂN TÁN VỚI RMI 14
2.1 Giới thiệu: 14
2.2 Kiến trúc RMI 16
2.2.1 Giao diện (interface) - trái tim của RMI: 16
2.2.2 Kiến trúc phân tầng của RMI 17
2.3 Cài đặt ứng dụng RMI đơn giản 222
2.4 MỘT SỐ KHÁI NIỆM TRONG RMI 26
2.4.1 Registry 26
2.4.2 Biến Classpath 28
2.4.3 Codebase 29
2.5 CHUYỂN THAM SỐ TRONG LỜI GỌI PHƯƠNG THỨC TỪ XA 31
2.5.1 Chuyển tham số theo tham trị và tham biến 31
2.5.2 Chuyển đối tượng đến trình chủ theo tham trị: 32
2.5.3 Chuyển đối tượng đến trình chủ theo tham biến: 37
2.6 TUẦN TỰ HÓA (SERIALIZABLE) ĐỐI TƯỢNG 41
2.7 MỘT SỐ KỸ THUẬT LẬP TRÌNH PHÂN TÁN VỚI RMI 45
2.7.1 RMI REGISTRY và cách đăng ký đối tượng 45
2.7.2 Dùng một đối tượng sản sinh nhiều đối tượng 48
2.7.3 Kỹ thuật gọi đối tượng ở xa bằng phương pháp động ( DYNAMIC METHOD INVOKE ) 54
Trang 22.7.4 Tự động kích hoạt đối tượng từ xa (ACTIVITION) 57
2.7.5 Trình mồi nạp ứng dụng từ xa 63
CHƯƠNG 3: LẬP TRÌNH PHÂN TÁN VỚI CORBA 69
3.1 TỔNG QUAN VỀ CORBA 69
3.1.1 Giới thiệu 69
3.1.2 Ngôn ngữ đặc tả là gì? 70
3.1.3 Ánh xạ giữa ngôn ngữ IDL và Java: 71
3.1.4 Corba và mô hình phân tán: 72
3.2 XÂY DỰNG ỨNG DỤNG CORBA TRONG MÔI TRƯỜNG JAVA 76
3.2.1 Các công việc phía Server: 76
3.2.2 Công việc phía Client: 80
3.2.3 Các cách khởi động trình môi giới ORB: 81
3.3 TÌM HIỂU JNDI VÀ DỊCH VỤ COS NAMING TRONG CORBA 83
3.3.1 JNDI và dịch vụ NAMING trong RMI 83
3.3.2 JNDI và dịch vụ COS NAMING của CORBA 83
3.3.3 Lưu địa chỉ tham chiếu của đối tượng CORBA ở dạng chuỗi – Kỹ thuật STRING FIELD (IOR): 93
3.4 MỘT SỐ KỸ THUẬT LẬP TRÌNH PHÂN TÁN VỚI CORBA 96
3.4.1 Tham chiếu ngược trong CORBA (CALLBACK) 96
3.4.2 Gọi các phương thức động trong CORBA (DYNAMIC METHOD CALL) 101
3.4.3 RMI trên IIOP (RMI over IIOP) 105
3.5 CORBA VÀ TRÌNH MÔI GIỚI ORB VISIBROKER 110
3.5.1 Giới thiệu 110
3.5.2 Xây dựng ứng dụng CORBA minh họa sử dụng VisiBroker 110
3.5.3 Biên dịch và triệu gọi đối tượng CORBA trong VisiBroker 114
3.5.4 Các đặc tả mới của CORBA và VisiBroker: 115
Trang 3PHẦN II:
XÂY DỰNG CHƯƠNG TRÌNH ỨNG DỤNG
Chương 1: ỨNG DỤNG LẬP TRÌNH PHÂN TÁN ĐỂ XÂY DỰNG HỆ THỐNG “TRIỂN KHAI THI VÀ CHẤM THI TRẮC NGHIỆM QUA MẠNG
LAN” 119
1.1 Đặt vấn đề 119
1.2 Xác định và đặc tả yêu cầu 119
1.3 Thiết kế hệ thống 127
1.3.1 Thiết kế kiến trúc 127
1.3.2 Thiết kế hệ thống 128
1.3.3 Sơ đồ lớp chi tiết của hệ thống 132
1.4 Một số giao diện của chương trình: 134
Tổng kết đề tài 138
Tài liệu tham khảo 139
Trang 4Danh mục hình ảnh
Hình 1.1-1: Mô hình triệu gọi các đối tượng từ xa 11
Hình 2.2-1: Biểu đồ minh họa hai lớp mô tả giao diện 17
Hình 2.2-2: Kiến trúc phân tầng của RMI 17
Hình 2.2-3: Hoạt động của các thành phần trong kiến trúc RMI 18
Hình 2.2-4: Vai trò của các lớp trung gian stub và skel 19
Hình 2.3-1: Triệu gọi đối tượng RMI Calculator từ xa 22
Hình 2.4-1: Cơ chế làm việc của trình khách và trình chủ trên máy ảo Java 26
Hình 2.4-2: Rmiregistry trong mô hình phân tán thực tế 27
Hình 2.4-3: Cơ chế nạp tự động lớp trung gian CalculatorImpl_Stub.class xuống máy khách 30
Hình 2.5-1: Trình chủ và trình khách có thể triệu gọi lẫn nhau 37
Hình 3.1-1: Triệu gọi đối tượng CORBA thông qua trình môi giới trung gian ORB 73
Hình 3.1-2: ORB giao tiếp với đối tượng thông qua các thông tin đặc tả 73
Hình 3.3-1: Cấu trúc cây của dịch vụ COS NAMING trong CORBA 84
Hình 3.4-1: Giao tiếp RMI-Over-IIOP giữa đối tượng trình chủ và trình khách 106
Hình 3.5-1: Cơ chế quản lý đối tượng của CORBA theo đặc tả mới 116
Hình 1.2-1: Ca sử dụng (use-case) quản lý đề thi 121
Hình 1.2-2: Ca sử dụng (use-case) triển khai đề thi 123
Hình 1.2-3: Ca sử dụng (use-case) đăng nhập 124
Hình 1.2-4: Ca sử dụng (use-case) làm bài thi 125
Hình 1.2-5: Ca sử dụng (use-case) xem kết quả thi 126
Hình 1.3-1: Kiến trúc tổng quát của hệ thống 127
Hình 1.3-2: Biểu đồ tuần tự lớp thiết kế thực hiện ca sử dụng soạn đề thi: 128
Hình 1.3-3: Biểu đồ tuần tự lớp thiết kế thực hiện ca sử dụng triển khai đề thi: 129
Hình 1.3-4: Biểu đồ tuần tự lớp thiết kế thực hiện ca sử dụng đăng nhập 130
Hình 1.3-5:Biểu đồ tuần tự lớp thiết kế thực hiện ca sử dụng làm bài thi 130
Hình 1.3-6: Biểu đồ tuần tự lớp thiết kế thực hiện ca sử dụng xem bài làm 131
Trang 5Hình 1.3-7: Biểu đồ tuần tự lớp thiết kế thực hiện ca sử dụng kết thúc bài làm 131
Hình 1.4-1: Giao diện soạn đề thi 134
Hình 1.4-2: Soạn câu hỏi có hình ảnh 135
Hình 1.4-3: Giao diện đăng nhập của thí sinh 135
Hình 1.4-4: Cảnh báo sai số báo danh 136
Hình 1.4-5: Giao diện bài làm của thí sinh 136
Hình 1.4-6: Cửa sổ khi chọn chức năng xem bài làm 137
Hình 1.4-7: Cảnh báo trước khi kết thúc bài làm 137
Hình 1.4-8: Kết quả bài thi của thí sinh 137
Trang 6Danh mục từ viết tắt
Trang 7Lý do chọn đề tài
Ngôn ngữ lập trình Java do công ty Sun Microsystems phát triển vào đầuthập kỷ 1990 Trải qua hơn 20 năm phát triển, Java thật sự đã lớn mạnh Hiện tại,Java đã có mặt trong hầu hết các lĩnh vực lập trình với các tên gọi quen thuộc nhưJava.net, RMI, JDBC, JSP, Servlet, Java Mail, J2ME…
Java đang rất được ưu chuộng bởi nhiều đặc điểm nổi bật của nó:
- Hướng đối tượng (Object - oriented): Đây là xu hướng lập trình phổ
biến nhất hiện nay
- Đa luồng (multithreaded): ngôn ngữ Java cho phép xây dựng trình
ứng dụng, trong đó nhiều quá trình có thể xảy ra đồng thời
- Mạnh mẽ (robust): Khả năng mạnh phải phù hợp với thiết kế của
ngôn ngữ, và hướng nó vào việc khắc phục những hư hỏng bộ nhớ và đảmbảo tính toàn vẹn dữ liệu Java làm được điều đó
- Tính động (dynamic): Java động vì nó được thiết kế để đáp ứng với
môi trường tác nghiệp luôn trong tình trạng thay đổi Khi có yêu cầu mớixuất hiện trên thị trường, các loại đối tượng mới có thể được bổ sung vàongay
- Hiểu mạng (network-savvy): Java được lập ra để hoạt động trên
mạng và có các thủ tục để có thể quản lý các giao thức mạng như TCP/IP,FTP và HTTP
- Độc lập với cấu trúc (architecture neutral): Java không phụ thuộc
vào hệ máy (platform - loại máy, hệ điều hành)
Có thể nói Java xuất hiện đã tạo ra một cuộc cách mạng trong công nghệphần mềm Java đang được phát triển từng ngày từng giờ bởi sự lao động khôngmệt mỏi và tầm nhìn chiến lược của các nhà phát triển nó
Chính vì những ưu điểm đó, bản thân em khi mới tiếp xúc với Java đã thấyyêu thích ngôn ngữ này Hơn nữa, với ý tưởng bài toán đặt ra ban đầu là xây dựngmột ứng dụng qua mạng nên em đã chọn mảng lập trình phân tán trong Java đểnghiên cứu và ứng dụng để xây dựng chương trình của mình
Trang 8PHẦN I:
TÌM HIỂU KỸ THUẬT LẬP TRÌNH PHÂN TÁN TRONG JAVA
1.1 Lập trình phân tán là gì?
Lập trình thông thường trên máy cục bộ: Các đối tượng của chương trình làthủ tục hay hàm được nạp trực tiếp vào bộ nhớ và thực thi ngay trên máy cục bộ.Đối với những hàm có sẵn trong thư viện, người ta không quan tâm đến các hàmnày cài đặt và làm việc như thế nào mà chỉ quan tâm đến tham số truyền cho nó vàkết quả trả về
Lập trình có sự giao tiếp giữa các máy khác nhau: tức là hai chương trình ởhai máy có thể gọi lẫn nhau Thực chất của việc giao tiếp này là sự giao tiếp của cácphương thức, các phương thức có thể gọi lẫn nhau Vậy thì làm cách nào cài đặtphương thức ở một máy và thực hiện lời gọi phương thức ở một máy khác? Đóchính là nội dung của lập trình phân tán
Có thể nói: lập trình phân tán là việc lập trình trên các máy khác nhau trong
đó các đối tượng của chương trình gồm phương thức và thuộc tính có thể triệu gọilẫn nhau
Computer A
Computer B
Computer C
A2 A1
B1
C2 C1
Hình 1.1-1: Mô hình triệu gọi các đối tượng từ xa
Trang 9Trong minh họa trên, các đối tượng A1 và A2 ở máy A có thể gọi nhau, B1
và B2 ở máy B cũng vậy, đó là lời gọi cục bộ Tuy nhiên, đối tượng A1 ở máy Acũng có thể gọi đối tượng C1 ở máy C hay B1 ở máy B cũng có thể gọi C1 ở máy
C, đó là những lời gọi từ xa
1.2 Vấn đề gọi phương thức từ xa
Trên máy cục bộ, các phương thức đều được chương trình quản lý và định
vị trong vùng nhớ, người lập trình có thể cho phép thực hiện lời gọi một cách bìnhthường mà không cần quan tâm đến việc chúng giao tiếp với nhau thế nào Còn cácphương thức ở các máy khác nhau hoạt động trên hai tiến trình, không gian địa chỉkhác nhau nên việc truyền tham số, tham chiếu đến địa chỉ của nhau không thể thựchiện thông thường như trong trong cùng một máy được
Lời gọi phương thức cục bộ luôn đưa về kết quả, có nghĩa là luôn thực hiệnđược trong khi việc gọi các phương thức từ xa có thể không thực hiện được do sự
cố mạng
Đối với hàm trên máy cục bộ, tham số truyền cho hàm thường được đưavào ngăn xếp rồi chương trình sẽ lấy ra để thực hiện trong khi tham số truyền chohàm ở xa phải được đóng gói và chuyển qua mạng theo giao thức mạng mới đếnđược nơi cần đến
1.3 Lập trình phân tán với Java
Có nhiều ngôn ngữ hỗ trợ lập trình phân tán, Java là một trong số đó vớihai thư viện chuẩn là RMI và CORBA Thực chất RMI là một cơ chế gọi phươngthức từ xa đã được tích hợp trong ngôn ngữ Java Vì Java là một ngôn ngữ lập trìnhhướng đối tượng, nên phương pháp lập trình trong RMI là phương pháp hướng đốitượng, do đó các thao tác hay các lời gọi phương thức đều liên quan đến đối tượng.CORBA (Common Object Request Broker Architecture) là đặc tả của OMG (ObjectManagement Group) dành cho việc đạt được tính tương tác giữa các nút tính toánphân tán Mục tiêu của CORBA là định nghĩa một cấu trúc mà có thể cho phép
Trang 10tâm đến người nào đã thiết kế ra hai điểm cuối của ứng dụng phân tán Corba là mộtngôn ngữ trung lập được thực thi rộng rãi hơn trên các nền platform khác nhau.Corba sử dụng một giao thức gọi là IIOP (Internet Inter-ORB Protocol) để liên lạcgiữa các hệ thống khác nhau.
Sự khác nhau giữa RMI và CORBA:
- RMI là một phần của bộ J2SDK và là các hàm thư viện hỗ trợ các lời gọi phươngthức từ xa và trả về giá trị cho các ứng dụng tính toán phân tán Ở đây ngôn ngữJava được sử dụng ở cả phía gọi và phía bên phương thức được gọi
- CORBA là một chuẩn công nghiệp cho phép gọi các phương thức từ xa và nhậnkết quả trả về Nhưng không giống như RMI, nó có thể được sử dụng khi bên phíagọi và bên phía phương thức được gọi có thể sử dụng các ngôn ngữ lập trình khácnhau, bao gồm cả trường hợp là cả hai bên đều không sử dụng ngôn ngữ Java
- RMI là một tập các hàm thư viện đơn giản vì cả hai bên đều sử dụng cùng mộtngôn ngữ lập trình và kiến trúc máy Điều này sẽ làm cho vấn để triệu gọi phươngthức từ xa dễ giải quyết hơn
- Bộ phát triển J2SDK cũng hỗ trợ cả RMI và CORBA, cho phép một đối tượngJava gọi một đối tượng CORBA sử dụng hai cách tiếp cận khác nhau
Trang 112 Chương 2: LẬP TRÌNH PHÂN TÁN VỚI RMI
1.1 Giới thiệu:
RMI (Remote Method Invoke)– triệu gọi phương thức từ xa - là công nghệđược SUN giới thiệu đầu tiên trong JDK 1.1 (2/1997), công nghệ này đã mở ra mộtthời kì mới cho lĩnh vực lập trình mạng Mặc dù được thiết kế tương đối dễ sử dụngnhưng RMI cũng là một công nghệ rất mạnh, cung cấp đầy đủ các công cụ để ngườilập trình có thể phát triển ứng dụng phân tán một cách tốt nhất
Trong JDK 1.1, RMI đã được tạo ra gần như đầy đủ và nó đã được bổ sunghoàn chỉnh hơn trong JAVA 2 SDK Ở mỗi ứng dụng, chúng ta sẽ thấy được sựkhác nhau giữa hai phiên bản này
Mục đích chính của việc thiết kế ra RMI là cho phép người lập trình pháttriển các chương trình phân tán bằng Java với cú pháp và ngữ nghĩa giống như lậptrình thông thường Để làm được việc này, họ đã ánh xạ các lớp và đối tượng làmviệc trong một máy ảo Java đơn thành các lớp và đối tượng làm việc trong một môitrường phân tán
Trong phạm vi bài khóa luận này, RMI được trình bày theo quan điểm lậptrình phân tán các đối tượng từ xa, hành vi của các đối tượng từ xa khác với các đốitượng cục bộ RMI định nghĩa hành vi của các đối tượng, và vấn đề ta cần quan tâm
là các đối tượng từ xa đó có thể thực thi khi nào và như thế nào, bộ nhớ được quản
lý ra sao, các thông số được truyền ra sao, kết quả trả về đâu và gọi phương thức từ
xa như thế nào…
So sánh lập trình phân tán và phi phân tán trong Java:
Định nghĩa
đối tượng Được định nghĩa bởi một lớp – class
Được định nghĩa bởi interface vàphải được kế thừa (extends) từ giaodiện Remote interface
Mô tả đối Được mô tả mở chính Hành vi của đối tượng từ xa được
Trang 12Tạo đối tượng
Dùng phương thức khởi tạo và từ khóa new
Một đối tượng từ xa được khởi tạotrên một máy tính theo cách thôngthường Một client không thể trựctiếp khởi tạo đối tượng từ xa
Truy xuất đối
tượng
Được truy xuất trựctiếp thông qua một biếntham chiếu đến đốitượng đó
Được truy cập thông qua một biếntham chiếu đến đối tượng nhưng làtham chiếu gián tiếp vì mọi tác độnglên đối tượng đều thông qua lớptrung gian và sau đó mới đến đốitượng
Tham chiếu
Trong một máy ảo javađơn, một đối tượngtham chiếu trỏ trực tiếpđến một đối tượng kháctrong vùng nhớ heap
Một tham chiếu từ xa là tức là mộtcon trỏ trỏ đến đối tượng trung giantrong vùng nhớ heap cục bộ Đốitượng trung gian cục bộ này chứathông tin cho phép nó có thể kết nốiđến đối tượng từ xa
Hoạt động
tham chiếu
Trong một máy ảo javađơn, một đối tượng sẽđược cho là “còn sống”
nếu có ít nhất một thamchiếu đến nó
Trong môi trường phân tán, việc liênlạc giữa các máy ảo Java có thể bịđứt do sự cố mạng Do vậy, một đốitượng từ xa được xem là có mộthành động tham chiếu đến nó nếu nó
đã được truy xuất trong một khoảngthời gian nhất định Nếu tất cả cáctham chiếu từ xa đã mất hoặc hết hạnthì một đối tượng từ xa sẽ được đượcgiải phóng
Finalization
Nếu một đối tượng càiđặt phương thứcfinalize(), nó được gọitrước khi đối tượngđược thu dọn bởi chứcnăng dọn rác
Nếu một đối tượng cài đặt giao diệnUnreferenced, phương thứcunreferenced của giao diện đó sẽđược gọi khi tất cả các tham chiếu từ
xa bị ngắt
Thu dọn rác
Khi tất cả các tham chiếu cục bộ đến một đối tượng bị ngắt, nó sẽđược xem là rác
Chức năng thu dọn rác phân tán liênkết làm việc với chức năng thu dọnrác cục bộ Nếu không có tham chiếu
từ xa nào và tất cả các tham chiếucục bộ đến một đối tượng bị ngắt, nó
RMI buộc các chương trình chịu bất
kì ngoại lệ nào củaRemoteException đưa ra Điều này
Trang 13java buộc một chươngtrình phải đảm nhiệmbắt tất cả các ngoại lệ
sẽ làm cho các việc ném ngoại lệ củacác ứng dụng phân tán được bảođảm
Bảng so sánh lập trình phân tán và phi phân tán trong Java
1.2 Kiến trúc RMI
2.1.1 Giao diện (interface) - trái tim của RMI:
Kiến trúc RMI dựa trên một nguyên lý quan trọng: định nghĩa hành vi vàviệc mô tả hành vi là hai khái niệm riêng biệt RMI chấp nhận mã của định nghĩahành vi và mã của mô tả hành vi tách rời nhau và chạy trên các máy ảo Java độclập
Điều cần làm của hệ thống phân tán là ở máy khách sẽ định nghĩa dịch vụmong muốn và máy chủ là nơi cung cấp các dịch vụ đó
Trong RMI, việc định nghĩa một dịch vụ từ xa được viết bằng interfacetrong Java Mô tả chi tiết dịch vụ từ xa được viết bằng một lớp - class Do đó, yếu tốchính cần hiểu trong RMI là: các giao diện định nghĩa hành vi của đối tượng từ xa
và các lớp mô tả định nghĩa đó
Hình 2.2-1: Giao diện và lớp mô tả giao diện
Một giao diện không chứa mã thực thi RMI hỗ trợ hai lớp mô tả giao diệngiống nhau Lớp thứ nhất là mô tả hành vi và nó chạy trên server Lớp thứ hai hoạtđộng như một đối tượng trung gian cho các dịch vụ từ xa và nó chạy trên Client
Trang 14Hình 2.2-2: Biểu đồ minh họa hai lớp mô tả giao diệnMột chương trình Client thực hiện lời gọi phương thức thông qua đối tượngtrung gian (proxy), RMI sẽ gửi đến máy ảo từ xa và từ đó đi đến đối tượng mô tả.Bất kì giá trị trả về nào được tạo ra bởi đối tượng mô tả sẽ được gửi trở về proxy vàsau đó proxy sẽ chyển đến chương trình trên máy khách
2.1.2 Kiến trúc phân tầng của RMI
RMI về cơ bản được xây dựng từ 3 lớp trừu tượng như mô hình dưới đây:
Hình 2.2-3: Kiến trúc phân tầng của RMI
<<Interface>>
Service
Service Proxy
Service Implementation RMI
Transport Layer
Remote Reference LayerStub & Skeletons Stub & Skeletons
Remote Reference LayerRMI
System
Trang 15Client Object
Stub
Remote Object
Hình 2.2-4: Hoạt động của các thành phần trong kiến trúc RMI
Bởi việc dùng kiến trúc phân lớp nên mỗi lớp có thể được cải tiến hoặcthay thế mà không ảnh hưởng đến tính chất của hệ thống Ví dụ như lớp transport cóthể được thay thế bởi một lớp theo phương thức kết nối UDP/IP mà không ảnhhưởng các lớp trên nó
Lớp trung gian (STUB và SKELETON)
Như trên đã nói, việc gọi các phương thức từ xa là không giống như gọicác phương thức thông thường trong cùng một máy Vì thế, trong lập trình phân tán,
cơ chế gọi từ xa là các đối tượng trên hai máy khác nhau không gọi trực tiếp lẫnnhau mà thông qua lớp trung gian Người lập trình không cần phải quan tâm lớptrung gian này chứa gì và làm việc ra sao Lớp trung gian này sẽ đón đầu các lời gọiphát sinh từ Client đến biến tham chiếu giao diện và gửi lại các lời gọi đó cho dịch
vụ RMI từ xa
Lớp trung gian tồn tại ở hai phía máy khách (nơi thực hiện lời gọi) và máychủ (nơi cài đặt đối tượng được gọi) Phía máy khách, lớp trung gian được gọi làStub và phía máy chủ, lớp trung gian được gọi là Skeleton
Trang 16Hình 2.2-5: Vai trò của các lớp trung gian stub và skel
Ví dụ: Ta có đối tượng C1 được cài đặt trên máy C Trình biên dịch Java sẽ
tạo ra 2 lớp là C1_Stub và C1_Skel C1_Stub được chuyển đến máy A Khi A1 trênmáy A gọi C1, nó sẽ chuyển lời gọi đến lớp C1_Stub C1_Stub chịu trách nhiệmđóng gói tham số, chuyển tham số qua mạng đến máy C Trên máy C, C1_Skel sẽnhận thông tin của A do C1_Stub chuyển đến và chuyển vào vùng không gian địachỉ thích hợp mà C1 sẽ làm việc Kết quả nếu có do phương thức của C1 trả về sẽđược lớp C1_Skel đóng gói trả ngược về cho C1_Stub C1_Stub sẽ chuyển giao kếtquả cuối cùng lại cho A1
Bằng cơ chế này, hai đối tượng ở hai máy khác nhau có thể làm việc vớinhau như là hai đối tượng cục bộ Hơn nữa, nếu mạng có sự cố thì lớp trung gianStub sẽ thông báo cho đối tượng tác động đến nó biết
Trong Java 2 SDK, lớp skeleton không còn nữa RMI dùng reflection đểtạo kết nối đến đối tượng dịch vụ từ xa
Remote Reference Layer
Lớp này được hiểu là làm phiên dịch và quản lý các tham chiếu tạo từClient đến đối tượng từ xa
Computer C
Computer C
C2 C1
C1_skel
Computer A Computer A
Computer B Computer B
A2 A1
B1 C1_stub
Trang 17Lớp Remote Reference Layers định nghĩa và hỗ trợ về ngữ nghĩa lời gọicủa kết nối RMI Lớp này cung cấp một đối tượng RemoteRef, đối tượng này đạidiện cho liên kết đến đối tượng thực hiện dịch vụ từ xa.
Đối tượng stub dùng phương thức invoke() trong RemoteRef để chuyển
tiếp lời gọi phương thức Đối tượng RemoteRef hiểu được ngữ nghĩa từ các lời gọi
từ xa
Trong JDK 1.1, RMI chỉ cung cấp một cách cho Client để kết nối đến dịch
vụ từ xa: unicast – một nối một Trước khi một Client có thể dùng dịch vụ từ xa,dịch vụ từ xa đó phải được cài đặt trên Server và được export trong RMI Nếu nó làdịch vụ chính, nó phải được đặt tên và đăng kí đến RMI Registry
Trong Java 2 SDK, RMI thêm một ý nghĩa mới cho kết nối client-server.Trong phiên bản này, RMI hỗ trợ đối tượng từ xa tích cực Khi một lời gọi phươngthức được tạo ra từ proxy đến một đối tượng activatable remote objects, RMI xácđịnh nếu đối tượng dịch vụ từ xa không hoạt động, RMI sẽ khởi tạo đối tượng vàkhôi phục trạng thái của nó từ một file trên đĩa
Có thể có các kiểu kết nối khác VD: với multicast, một proxy đơn có thểgửi cùng một yêu cầu đến nhiều đối tượng mô tả đồng thời… và nhận về sự đáp trảđầu tiên
Transport Layer - Tầng vận chuyển
Tầng này có nhiệm vụ tạo kết nối giữa hai máy ảo Java (JVM) Tất cả các kết nối là kết nối mạng cơ bản dùng giao thức TCP/IP
Nếu hai máy ảo đang chạy trên một máy vật lý, chúng kết nối thông quagiao thức ngăn xếp TCP/IP của chính máy tính đó Điều này lí giải tại sao ta phải cómột cấu hình TCP/IP trên máy tính khi ta chạy các ví dụ
TCP/IP cung cấp một kết nối an toàn giữa hai máy dựa trên địa chỉ IP và sốhiệu cổng Trong phiên bản RMI hiện tại, kết nối TCP/IP được dùng là cơ bản cho tất cả các kết nối từ máy này đến máy khác
Lúc đầu dùng TCP/IP, RMI dùng giao thức JRMP, giao thức này là duynhất Nhưng về sau, đã có hai phiên bản Phiên bản đầu tiên được phát hành với
Trang 18JDK 1.1, RMI yêu cầu dùng lớp Skeleton trên server Phiên bản thứ 2 được pháthành với Java 2 SDK Nó đã được cải tiến để đạt hiệu năng và không yêu cầu lớpskeleton Một vài thay đổi với Java 2 SDK là interface không đòi hỏi kế thừa từjava.rmi.Remote và các phương thức không cần thiết ném ra ngoại lệRemoteException
SUN và IBM đã liên kết làm việc cho phiên bản mới của RMI được gọi làRMI-IIOP, RMI-IIOP dùng giao thức IIOP để thay thế cho JRMP
Trang 191.3 Cài đặt ứng dụng RMI đơn giản
Ở ứng dụng phân tán RMI đơn giản này, ta cần có hai chương trình, mộtchương trình chạy ở Server sẽ chờ phục vụ yêu cầu tính toán và một chương trìnhyêu cầu chạy ở máy Client
Hình 2.3-6: Triệu gọi đối tượng RMI Calculator từ xa
Ở chương trình trên Server, ta cần mô tả lớp giao tiếp của đối tượngCalculator, sau đó cài đặt chi tiết cho đối tượng Calculator và đưa cài đặtnày vào trong một chương trình điều khiển gọi là CalculatorServer
o Đầu tiên, ta đặc tả lớp giao tiếp của đối tượng Calculator:
từ nó (Calculator) có khả năng giao tiếp từ xa
o Cài đặt chi tiết cho đối tượng Calculator:
Trang 20class CalculatorImpl implements Calculator
UnicastRemoteObject.exportObject(c);
Lệnh này để cho máy ảo Java nhận diện được đối tượng c là đối tượng có khả nănggiao tiếp từ xa
Naming.bind("rmi://localhost/CalcProg",c);
Trang 21Mục đích: đặt cho đối tượng c một tên gợi nhớ và đăng kí tên này với bộ quản lýRMI Các chương trình ở máy khách sẽ dựa vào tên này để tham chiếu đến đốitượng tương ứng.
Cú pháp của phương thức bind(rmi://hostname:port/ObjectName,Object)
- rmi: là giao thức dùng để đăng kí
- hostname:port: địa chỉ IP hoặc tên máy và số hiệu cổng của máy nơi
mà bộ đăng kí RMI đang chạy
- ObjectName: tên gợi nhớ đặt cho đối tượng (Object) cần đăng kí
Bộ đăng kí rmiregisty: ta cần chạy bộ đăng kí này trước khi chạy chương trình CalculatorServer Khi thực thi, bộ rmiregistry sẽ chờ để đón nhận các kết nối của phương thức Naming.bind() gửi đến Mặc định, rmiregistry sẽ các
kết nối gửi đến cổng 1099 Ta có thể thay đổi số hiệu cổng này
Các bước chạy chương trình:
- Dịch và tạo _stub cho đối tượng phục vụ:
Trang 22Lệnh rmic CalculatorImpl: Tạo ra lớp trung gian CalculatorImpl_Stub.class TrongJ2SDK không dùng đến CalculatorImpl_Skel.class nữa.
- Chạy trình rmiregistry:
- Chạy chương trình CalculatorServer:
- Copy file Calculator.class và CalculatorImpl_Stub.class vào thư mục CalcClient.Thư mục này được xem như là một máy Client
- Chạy chương trình CalculatorClient:
Trang 231.4 MỘT SỐ KHÁI NIỆM TRONG RMI
2.1.3 Registry
Bộ đăng ký Registry dùng để tiếp nhận đăng ký tên của đối tượng giao tiếp
từ xa Trước khi máy khách muốn sử dụng được các phương thức và gọi được cácđối tượng từ xa, nó phải liên lạc với rmiregistry để lấy về tham chiếu đến đối tượngtrên máy chủ Dịch vụ đăng ký và truy tìm đối tượng được Java quản lý bằng cáchàm giao tiếp API JNDI (Java Naming Directory Interface) Các hàm JNDI ở máy
khách (Naming.lookup()) sẽ liên lạc với rmiregistry để nhận về tham chiếu đến đối tượng trong khi đó các hàm JNDI ở máy chủ (Naming.bind()) có nhiệm vụ đăng ký
tên đối tượng với rmiregistry
Lưu ý:
Hàm Naming.bind() chỉ đăng ký tên đối tượng với rmiregistry đúng mộtlần Vì vậy nếu tên đăng ký đã tồn tại khi thực hiện hàm này sẽ nhận được thôngbáo lỗi AlreadyBoundException Để khắc phục, ta cần tắt chương trình rmiregistry
và chạy lại Tuy nhiên, ta có thể tránh điều đó bằng cách sử dụng hàmNaming.rebind() thay cho Naming.bind() Hàm Naming.rebind() có nhiệm vụ yêucầu đăng ký mới tên đối tượng với rmiregistry nếu tên này chưa có và đăng ký lạinếu tên đối tượng đã được đăng ký
Cơ chế làm việc của trình khách và trình chủ trên máy ảo Java khi đăng ký
và truy xuất rmiregistry:
Trang 24Đối tượng trên máy ảo Java B dùng hàm Naming.bind() hoặc hàmNaming.rebind() để đăng ký đối với tượng với chương trình rmiregistry đang chạytrên máy ảo Java A
Chương trình khách chạy trên máy ảo Java C dùng hàm Naming.lookup() đểyêu cầu bộ quản lý rmiregistry trên máy ảo A trả về tham chiếu đến đối tượng
Bộ quản lý trên máy ảo A trả về tham chiếu đến đối tượng đang tồn tại trên máy
ảo B
Chương trình khách chạy trên máy ảo C sử dụng tham chiếu do hàmNaming.lookup() trả về để truy và gọi phương thức của đối tượng đang chạy trênmáy ảo B từ xa
Ba máy ảo này có thể xem là ba máy tính khác nhau nhưng do chạy trêncùng một máy nên địa chỉ giống nhau là localhost
Thực tế mô hình trên muốn hoạt động trên mạng thật thì chỉ có thể tách ralàm hai chứ không thể tách ra ba, vì Java không cho phép rmiregistry chạy trên máy
khác nơi đối tượng rmi đang hoạt động
Ví dụ:
Hình 2.4-8: Rmiregistry trong mô hình phân tán thực tếLúc này hàm đăng ký với rmiregistry được gọi như sau:
Naming.bind(“rmi://172.16.11.12/ CalcProg”,c);
Và hàm truy tìm đối tượng từ máy khách sẽ được gọi như sau:
Calculator c = (Calculator) Naming.lookup(“rmi://172.16.11.12/CalcProg”);
Trang 252.1.4 Biến Classpath
CLASSPATH là một biến môi trường(environment variable) được sử dụngbởi Java compiler và JVM để tìm kiếm các lớp cần thiết cho quá trình biên dịch(compile) và thông dịch(interpret) Khi chạy chương trình, Java dựa vào biến môitrường CLASSPATH để truy tìm các tập tin class Nếu CLASSPATH chỉ saiđường dẫn, chương trình sẽ thông báo lỗi: java.lang.ClassNotFoundException:ClassName
Trong ví dụ ứng dụng RMI đơn giản trên, ta có các lớp sau:
Calculator.class Đặc tả các phương thức giao tiếp của đối tượng Server & ClientCalculatorImpl.class Cài đặt chi tiết đối tượng Server
CalculatorServer.class Tạo ra đối tượng và đăng ký đối tượngvới rmiregistry Server
CalculatorImpl_Stub.class Lớp giao tiếp trung gian Server & ClientCalculatorClient.class Gọi các phương thức của đối tượng
Khi CalculatorServer yêu cầu rmiregistry đăng ký tên đối tượng,rmiregistry sẽ đi truy tìm lớp trung gian CalculatorImpl_Stub.class Trên máy ảormiregistry đang chạy nếu CLASSPATH không trỏ đến đường dẫn E:\Luanvan\
EXAM\First\ (CalculatorImpl_Stub.class nằm ở đường dẫn này) thì nhận được
thông báo lỗi trả về trên máy ảo nơi CalculatorServer yêu cầu đăng ký đối tượng:
Trang 26Khi thay đổi giá trị cho Classpath ở một máy ảo sẽ không làm ảnh hưởng tớiClasspath của máy ảo khác.
2.1.5 Codebase
Thật sự khi viết chương trình từ phía máy khách, lập trình viên chỉ cần đếnlớp giao tiếp Calculator.class Lớp trung gian CalculatorImpl_Stub.class không có ýnghĩa đối với các nhà phát triển ứng dụng Nó chỉ cần thiết cho cơ chế RMI củaJava
Chính vì điều này Java cung cấp cho ta cách thức nạp tự động lớpCalculatorImpl_Stub.class từ xa thông qua tùy chọn Codebase khi đăng ký đốitượng với rmiregistry trên máy chủ
Ở máy chủ phải hỗ trợ thêm dịch vụ Web Server chạy trên máy nơirmiregistry đang chạy Sau đó ta chép tập tin CalculatorImpl_Stub.class vào thưmục myclass của trình chủ web server Khi sử dụng tùy chọn Codebase thì biếnClasspath trên máy ảo nơi rmiregistry đang chạy không được trỏ đến cùng thư mụcchứa CalculatorImpl_Stub.class Nếu không rmiregistry sẽ luôn ưu tiên lấy lớpCalculatorImpl_Stub.class từ đường dẫn Classpath mà bỏ qua tùy chọn Codebase.Câu lệnh để chạy chương trình trên máy chủ được sửa lại như sau:
java CalculatorServer –Djava.rmi.server.codebase=”http://172.16.11.12/myclass/”
Khi máy khách có yêu cầu rmiregistry trả về tham chiếu của đối tượng, nếumáy khách chưa có lớp CalculatorImpl_Stub.class, rmiregistry sẽ hướng dẫn máykhách tự động nạp lớp này từ địa chỉ codebase: http://172.16.11.12/myclass/
Trang 27Hình 2.4-9: Cơ chế nạp tự động lớp trung gian CalculatorImpl_Stub.class xuống
máy kháchTrình chủ CalculatorServer đăng ký đối tượng với remiregistry.CalculatorServer yêu cầu bộ quản lý rmiregistry truy tìm lớpCalculatorImpl_Stub.class ở địa chỉ URL http://172.16.11.12/myclass/
java CalculatorServer –Djava.rmi.server.codebase=”http://172.16.11.12/myclass/”Rmiregistry nhận được yêu cầu đăng ký đối tượng nó sẽ truy tìm lớpCalculatorImpl_Stub.class trong lớp Classpath Nếu không thấy, rmiregistry sẽ dựavào chuỗi URL do trình CalculatorServer cung cấp yêu cầu Web server trả về lớptrung gian này Rmiregistry ghi nhớ lại địa chỉ URL nơi lớp trung gianCalculatorImpl_Stub đang được lưu trữ
Chương trình ở máy khách yêu cầu rmiregistry trả vế tham chiếu của đối tượng.Nếu phía máy khách chưa tồn tại lớp CalculatorImpl_Stub.class bộ quản lýrmiregistry sẽ cho trình khách biết địa chỉ URL để nạp lớp trung gian này về
Chương trình ở máy khách yêu cầu Web Server cung cấp lớp trung gian http://172.16.11.12/myclass/CalculatorImpl_Stub.class
Trình khách sử dụng lớp trung gian CalculatorImpl_Stub.class và lớp giao tiếpCalculator.class để gọi các phương thức của đối tượng trên máy chủ
Trang 281.5 CHUYỂN THAM SỐ TRONG LỜI GỌI PHƯƠNG THỨC TỪ XA
2.1.6 Chuyển tham số theo tham trị và tham biến
Đối với Java, trên máy cục bộ, hầu hết các biến kiểu đối tượng đều truyềntheo tham biến trong các lời gọi hàm Nghĩa là một khi biến đối tượng được truyềnvào phương thức, nếu bên trong phương thức thay đổi giá trị của đối tượng thì khilời gọi phương thức chấm dứt, giá trị của đối tượng cũng thay đổi theo Ví dụ:
class Number{
public int value=0;
public Number (int v) {
public static void main (String args[]){
Number num=new Number(12);
class Program{
public static void doIncease(int n) {
n++;
Trang 29Việc truyền tham số qua mạng theo cơ chế RMI lại khác với cách truyềntham số thông thường Tất cả các dữ liệu kiểu đối tượng muốn truyền qua mạng đều
buộc phải cài đặt một trong hai giao tiếp Remote hoặc Serializable Các đối tượng
cài đặt giao tiếp Remote sẽ được truyền theo tham biến còn các đối tượng cài đặtgiao tiếp Serializable sẽ được tuyền theo tham trị Còn tất cả các kiểu dữ liệu đơngiản như int, char… đều được truyền theo tham trị
2.1.7 Chuyển đối tượng đến trình chủ theo tham trị:
Hầu như các kiểu dữ liệu đối tượng cơ bản như String, Date, Time…trongJava đều cài đặt giao diện Serializable, cho nên chúng được chuyển cho các lời gọiphương thức từ xa theo tham trị
Tương tự lớp Remote, lớp Serializable chỉ là một lớp rỗng dùng cho mụcđích báo hiệu Tất cả các lớp đối tượng cài đặt giao diện Serializable đều được Javaxem là có khả năng tuần tự hóa (serialize) Nghĩa là ta có thể yêu cầu Java lưu toàn
bộ đối tượng lên đĩa cứng thành một tập tin nào đó, sau đó đem tập tin này đến máykhác, ta có thể khôi phục lại đối tượng về trạng thái ban đầu mà không cần phảikhởi tạo đối tượng mới bằng lệnh new
Với cơ chế truyền tham số đối tượng theo tham trị, khi ta viết chương trìnhgọi một phương thức của đối tượng ở xa, nếu trong lời gọi có yêu cầu tham số kiểu
Trang 30nhận tham số thực thi phương thức) Tại máy chủ, đối tượng sẽ được mở ra, trở lạitrạng thái ban đầu và đưa vào sử dụng Quá trình đóng gói tham số trên máy khách
để chuyển đi được thực hiện bởi lớp trung gian Stub Ngược lại, quá trình mở gói
dữ liệu để khôi phục tham số diễn ra trên máy chủ được thực hiện bởi lớp trung gianSkel Quy trình chuyển tham số và dữ liệu qua lại giữa hai lớp trung gian Stub vàSkel trong thuật ngữ lập trình phân tán gọi là mashaling data
Trong các lời gọi phương thức RMI, kiểu dữ liệu đối tượng nếu không càiđặt một trong hai giao tiếp Serializable hoặc Remote thì sẽ không thể dùng làmtham số chuyển qua mạng được
Chương trình minh họa chuyển tham số đối tượng qua mạng:
Dưới đây là một chương trình ví dụ minh họa cho thấy cách chuyển một đốitượng từ máy khách đến máy chủ Chương trình này giống như trò chơi ném bóng,trình khách sẽ ném một quả bóng (đối tượng Ball) đến máy chủ, trình chủ sẽ tiếpnhận quả bóng và trả về cho trình khách
Bước 1: Thiết kế lớp đối tượng Ball.class được dùng làm tham số chuyển qua mạng
Trang 31Lớp Ball dùng để biểu diễn một quả banh có trọng lượng weight Mục đíchcủa ta là sử dụng đối tượng Ball để làm tham số di chuyển trên mạng giữa trìnhkhách và trình chủ, cho nên lớp Ball được khai báo là có khả năng tuần tự hóa.
Bước 2: Đặc tả interface cho đối tượng trên máy chủ
//PingServer.java
import java.rmi.*;
interface PingServer extends Remote {
public Ball ping(Ball b) throws RemoteException;
}
Đối tượng PingServer được đặt trên trình chủ Phương thức ping() của đốitượng này sẽ được gọi bởi trình khách Trình khách sử dụng phương thức ping() đểném quả bóng lên trình chủ thông qua tham số có kiểu đối tượng là Ball Sau khitiếp nhận đối tượng Ball, trình chủ sẽ trả lại đối tượng này cho trình khách
Bước 3: Cài đặt chi tiết cho giao diện PingServer
//PingServerImpl.java
import java.rmi.*;
class PingServerImpl implements PingServer{
public Ball ping(Ball b) throws RemoteException {
System.out.println(“Client send a ball objectweight” + b.getWeight());
Trang 32import java.rmi.*;
import java.rmi.server.*;
class Setup {
public static void main(String args[]) throws Exception{
PingServer server=new PingServerImpl();
public static void main(String args[]) throws Exception{
Ball ball=new Ball(12);
PingServer server=
(PingServer)Naming.lookup("rmi://localhost/pingobject"); System.out.println("Ball weight before send to server "+ball.getWeight()); Ball anotherBall=server.ping(ball);
System.out.println("Ball weight after send to server "+ball.getWeight()); System.out.println("Ball weight return by server ”
+anotherBall.getWeight());
}
}
Các bước thực hiện chương trình:
- Để đơn giản, ta gom tất cả các lớp vào một thư mục, ở đây là E:\Luanvan\EXAM\Ball
Trang 33Nếu bỏ thuộc tính Serializable của lớp Ball, quá trình biên dịch vẫn thànhcông nhưng khi thực thi, chương trình sẽ phát hiện lỗi và ném ra ngoại lệ như sau:
java.io.NotSerializableException:Ball
Trang 342.1.8 Chuyển đối tượng đến trình chủ theo tham biến:
Ở ví dụ chuyền quả banh trên, đối tượng Ball được di chuyển qua lại giữatrình khách và trình chủ, mỗi lần truyền đi lại phải đóng gói và truyền theo giaothức mạng Nếu kích thước đối tượng quá lớn thì sẽ ảnh hưởng đến tốc độ thực hiệncủa chương trình Vấn đề đặt ra ở đây là có cách nào để trình khách có thể yêu cầutrình chủ tham chiếu và xử lý trực tiếp đối tượng trên trình khách hay không? Cónghĩa là trình chủ được trình khách truy xuất từ xa thì trình khách cũng được trìnhchủ truy xuất từ xa
Đối tượng trên
máy khách
Đối tượng trên máy chủ Gọi phương thức
Gọi phương thức
Hình 2.5-10: Trình chủ và trình khách có thể triệu gọi lẫn nhau
Như trên đã nói, với Java, các đối tượng nếu cài đặt giao diện Remote sẽ cókhả năng được truyền qua mạng theo tham biến Cơ chế gọi ngược từ xa từ trìnhchủ đến trình khách còn được gọi là cơ chế callback
Chương trình minh họa chuyển đối tượng qua mạng theo tham biến:
Chương trình sau cho thấy cách cài đặt kĩ thuật callback triệu gọi lẫn nhaugiữa đối tượng trên trình khách và đối tượng trên trình chủ sử dụng tham biến Ta sẽtạo ra hai đối tượng, đối tượng AtClient chạy trên máy khách và đối tượngAtServer chạy trên máy chủ Đầu tiên, như cách làm ở các ví dụ trước, trình khách
sẽ liên lạc với rmiregistry để tìm tham chiếu đến đối tượng AtServer trên máy chủ
Trang 35Tiếp đến, trình khách sẽ tạo ra đối tượng AtClient ngay trên máy khách và gọiphương thức của đối tượng AtServer từ xa để đăng kí đối tượng AtClient với trìnhchủ Bắt đầu từ thời điểm đó, đối tượng AtClient trên máy khách và AtServer trênmáy chủ có thể tự do điều khiển và triệu gọi lẫn nhau Các bước cài đặt chươngtrình như sau:
Bước 1: Đặc tả interface cho đối tượng AtClient
//AtClient.java
import java.rmi.*;
interface AtClient extends Remote {
public void callClientMethod(String message) throws RemoteException;}
Bước 2: Đặc tả interface cho đối tượng AtServer
//AtServer.java
import java.rmi.*;
interface AtServer extends Remote {
public void registerClient(AtClient c) throws RemoteException;
public void callServerMethod(String message) throws RemoteException;}
Bước 3: Cài đặt chi tiết cho đối tượng AtClient thông qua lớp AtClientImpl
//AtClientImpl.java
import java.rmi.*;
class AtClientImpl implements AtClient {
public void callClientMethod(String message) throws RemoteException { System.out.println(message);
class AtServerImpl implements AtServer {
AtClient client; // lưu giữ tham chiếu đến đối tượng trên máy khách
Trang 36// phương thức này được trình khách triệu gọi để đăng ký đối tượng AtClient với trình chủ
public void registerClient(AtClient c) throws RemoteException {
client = c;
}
public void callServerMethod(String message) throws RemoteException { System.out.println(message);
for (int i=1; i<10; i++) {
String msg= "Server response "+ Math.random()*1000;
// Triệu gọi phương thức của đối tượng chạy trên máy khách client.callClientMethod(msg);
public static void main(String args[]) throws Exception{
AtServer server=new AtServerImpl();
public static void main(String args[]) throws Exception{
AtClient client=new AtClientImpl();
UnicastRemoteObject.exportObject(client);
AtServer server=(AtServer)Naming.lookup("rmi://localhost/serverobject");
Trang 37sẽ gọi phương thức registryClient() để cho phép trình chủ tham chiếu được đến đốitượng AtClient trên máy khách Sau đó, trình chủ sẽ không cần phải dùng phươngthức Naming.lookup() để tìm tham chiếu đến đối tượng AtClient trên rmiregistrynữa.
Trang 38Khi trình khách gọi phương thức callServerMethod() của đối tượngAtServer trên máy chủ, phương thức này lại sử dụng phương thứccallClientMethod() của đối tượng AtClient trên máy khách Trước khi gọicallClientMethod(), trình chủ thực hiện một số Calculator (sinh số ngẫu nhiên), kếtquả Calculator sau đó được chuyển cho trình khách và trình khách tự động in ra kếtquả Nếu như không dùng kĩ thuật callback thì trình chủ sẽ không có cách nào liênlạc với trình khách để trả về kết quả trực tiếp Khi đó, có hai cách để trình kháchnhận được kết quả gián tiếp:
- Cách thứ nhất: Trình chủ chủ động đóng gói tất cả các kết quả Calculator (sốngẫu nhiên) sau khi thực hiện xong rồi gửi cho trình khách Trình khách sẽ hiển thịkết quả nhận được Cách này giống như ví dụ ném bóng
- Cách thứ hai: Trình khách chủ động yêu cầu trình chủ trả kết quả sau một khoảngthời gian nhất định nào đó
Ta thấy cả hai cách đều có nhược điểm Vì thế, áp dụng kĩ thuật callback là tối ưu
Lưu ý: Nếu ta cài đặt cả 2 giao tiếp Remote và Serializable thì đối tượng sẽ
cùng lúc có 2 khả năng vừa có thể dùng làm tham biến và vừa có thể làm tham trị.Nếu ta dùng lệnh UnicastRemoteObject.exportObject() cho đối tượng thì nó sẽ đượctruyền đi theo tham biến, nếu không dùng lệnh này thì đối tượng sẽ được truyền đitheo tham trị
1.6 TUẦN TỰ HÓA (SERIALIZABLE) ĐỐI TƯỢNG
Java cung cấp khả năng ghi toàn bộ đối tượng xuống một tập tin Sau đó cóthể đem tập tin chứa đối tượng đi khắp nơi nếu cần thì khôi phục đối tượng về trạngthái ban đầu Đối tượng trong bộ nhớ có thể quan hệ chằng chịt với nhau nhưng khiđược ghi xuống tập tin thì bắt buộc phải trải phẳng đối tượng theo thứ tự
Trong Java đối tượng muốn có khả năng ghi và lưu dữ liệu thành tập tin taphải cài đặt giao tiếp java.io.Serializable Nếu đối tượng cần ghi chứa bên trongnhiều đối tượng con khác thì Java lấy tất cả các đối tượng con ghi luôn xuống đĩa
Dưới đây là ví dụ cho thấy khả năng tuần tự hóa của một đối tượng phứchợp
Trang 39// WriteObjectApp.java
import java.io.*;
class LinkObject implements Serializable {
static int count=1;
}
public String toString() {
return (“Object ” + id);
new FileOutputStream (“objects.dat”));
// khởi tạo đối tượng trong bộ nhớLinkObject X = new LinkObject (1);
catch (IOException e) {System.out.println (e);}
}
}
Thực thi chương trình:
Trang 40Như ta thấy, khi khởi tạo đối tượng LinkObject, phương thức khởi tạo củaLinkObject tự động tạo ra 50 đối tượng khác liên kết với nhau thành một danh sáchliên kết Do LinkObject cài đặt giao tiếp Serializable nên nó có khả năng ghi đượcthành tập tin trên đĩa
Chúng ta sử dụng lớp nhập xuất OjectOutputStream để ghi đối tượng X lêntập tin, khi đó toàn bộ 50 đối tượng liên kết với nó cũng được ghi vào tập tin đó.Giả sử một thời gian sau, ta muốn sử dụng lại đối tượng X, ta có thể đọc và khôiphục lại đối tượng từ tập tin objects.dat như sau:
ObjectInputStream in = new ObjectInputStream (
new FileInputStream (“objects.dat”));// đọc đối tượng từ tập tin
LinkObject X = (LinkObject) new in.readObject();
// in nội dung của đối tượng lên màn hìnhSystem.out.println(“Here is X” + X);
while ((X = X.next) != null)
System.out.println(X);
}catch (ClassNotFoundException d) { System.out.println(d);}
catch (IOException e) { System.out.println(e);}
}