Hiển thị các bài đăng có nhãn Java. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Java. Hiển thị tất cả bài đăng

[Java] Giáo trình lập trình mạng với Java DHSPKTHCM

Người đăng: share-nhungdieuhay on Thứ Năm, 10 tháng 7, 2014

More about

[LTM] Chương 9 : RMI (Remote Method Invocation)

Người đăng: share-nhungdieuhay on Thứ Tư, 7 tháng 5, 2014


Nội dung
Giới thiệu
Hoạt động của RMI
Hoạt động của lớp trung gian
Thiết kế và cài đặt một chương trình RMI
Thực thi hệ chương trình RMI, ex
Chuyển tham số trong RMI, ex
Tham trị
Tham chiếu
Tuần tự hóa đối tượng, ex
Factory Object, ex
RMI với firewall
Giới thiệu
Lập trình HĐT phân tán:
Môi trường hợp tác
Tận dụng nguồn tài nguyên phân tán trên mạng
Java: giải quyết vấn đề lập trình phân tán
Có .NET của Microsoft
Trong Java, sử dụng kỹ thuật RMI để cài đặt các đối tượng phân tán.
KT xuyên  suốt trong toàn bộ kiến trúc của Java

Giới thiệu
Local method Invocation: mã lệnh của hàm (hay thủ tục)  được nạp thẳng vào bộ nhớ và thực thi ngay trên máy cục bộ
Muốn nạp nội dung hàm hay đối tượng ở 1 máy nào đó gọi chúng từ một máy khác? 
Remote  Method  Invocation (RMI) : là cách thức giao tiếp giữa các đối tượng Java có mã lệnh cài đặt nằm trên máy khác nhau có thể gọi lẫn nhau.
Mô hình triệu gọi các đối tượng từ xa
RMI và RPC (Remote Procedure Calling)
Like RPC ,RMI has the following similarities
Remote calls can be made
Client/server contract based on interface
Unlike
RPC : hỗ trợ đa ngôn ngữ
RMI: chỉ hỗ trợ các ứng dụng được viết bằng Java
RMI – Client/Server
Mục đích của RMI 
Hỗ trợ gọi phương thức từ xa trên các đối tượng trong các máy ảo (JVM) khác nhau 
Tích hợp mô hình đối tượng phân tán vào ngôn ngữ lập trình Java theo một cách tự nhiên, có tin cậy trong khi vẫn duy trì các ngữ cảnh đối tượng của ngôn ngữ lập trình Java 
Làm cho mô hình đối tượng phân tán và mô hình đối tượng cục bộ không có sự khác biệt. 
Vấn đề phát sinh
Việc gọi phương thức của đối tượng từ xa luôn phức tạp hơn gọi phương thức cục bộ: 
Việc tham chiếu đến biến, địa chỉ của đối tượng khác nhau ở các máy khác nhau 
Các tham số truyền cho phương thức của đối tượng ở xa phải được đóng gói và chuyển qua mạng đến phương thức thực sự. (local-stack)
Lời gọi phương thức từ xa phải thông qua mạng và có thể bị ngắt ngang do mạng gặp sự cố 
Phụ thuộc vào kết nối mạng


Giải pháp
Đối tượng trên hai máy khác nhau không gọi trực tiếp mà thông qua lớp trung gian. 
Lớp trung gian tồn tại ở cả hai phía Client và Server.  
Lớp ở máy Client gọi là Stub, 
Lớp ở máy Server gọi là Skel(Skeletion)
Lớp trung gian Stub sẽ biết cách thông báo lỗi khi có các sự cố về mạng cho Client
Lớp trung gian Stub và Skeletion
Lớp trung gian Stub và Skeletion
Trình biên dịch Java (rmic.exe) sẽ tạo ra 2 lớp trung gian:
Lớp Stub (lớp móc): chuyển về cho client
Lớp Skeleton (lớp nối): Phía Server
Stub và Skeletion sẽ giúp các đối tượng ở xa giao dịch với nhau ?
Đối tượng trên máy Server cần cung cấp một giao diện tương ứng với các phương thức của nó (Server Object) cho phép đối tượng Client gọi nó trên máy Client dễ dàng.
Đối tượng client sẽ luôn nghĩ rằng nó đang hoạt động trực tiếp với đối tượng server trên máy cục bộ.
Lớp trung gian Stub và Skeletion
Ví dụ: 
Phương thức A truyền cho phương thức B hai số a,b. Phương thức B sẽ cộng hai số a,b cho ra kết quả c và trả về phương thức A. 

Kiến trúc của RMI
Kiến trúc của RMI
Quá trình hoạt động của RMI
Quá trình hoạt động của RMI
B1: RMI-server đăng ký tên của đối tượng với bộ q.lý Registry.
B2: Bộ quản lý Registry trả về tham chiếu đến đối tượng ở xa (RMI Server) thông qua lớp giao tiếp
B3-4: RMI-client liên lạc với bộ Registry để lấy về tham chiếu đến đối tượng trên Server. 
Các quá trình đăng ký và truy tìm tên đối tượng được Java quản lý bằng các hàm giao tiếp API JNDI
B5-7: Client sẽ gọi các phương thức của đối tượng trên Server
Khi một phương thức được gọi, sẽ được chuyển tiếp đến lớp trung gian Stub, rồi gọi đến lớp Skeleton (hđ Stub).
B8-10: Lớp Skeleton sẽ trực tiếp yêu cầu đối tượng thực thi phương thức và trả kết quả cho Client (hđ Skeletion)

Trình (bộ quản lý)đăng ký Registry
là một chương trình dịch vụ chạy ở hậu trường (rmiregistry.exe), thực hiện mở ổ cắm socket và lắng nghe các yêu cầu gởi đến cổng mặc định 1099, có thể chỉ định một cổng khác với cổng 1099.
Ví dụ: C:\j2sdk1.4.0\bin\ rmiregistry.exe 9999
Đóng vai trò như là một DNS nhỏ cho các đối tượng từ xa thực hiện tìm kiếm dịch vụ, 
Hoạt động của Stub, Skeleton
RMI trong JAVA
 Các lớp và các giao tiếp trong gói java.rmi
Giao tiếp Remote 
Lớp Naming
RemoteObject class
RemoteServer class
UnicastRemoteObject class
Giao tiếp Registry



RMI trong JAVA - Lớp Naming
Lớp java.rmi.Naming truyền tin trực tiếp với một trình đăng ký đang chạy trên server để ánh xạ các URL rmi://hostname/Objectname thành các đối tượng từ xa cụ thể trên host xác định:
Rmi là giao thức dùng để đăng kí. 
Hostname và port của Server nơi bộ Registry đang chạy. 
Objectname là tên tự đặt, phía client sẽ dựa vào tên này để truy tìm tham chiếu đến đối tượng cần dùng.
URL rmi  vs. URL http.

Naming class - methods
Lớp Naming cung cấp các phương thức sau: 
public static String[] list(String url) throws RemotException 
trả về một mảng các xâu ký tự, mỗi xâu là một URL đã được gắn với một tham chiếu. url là URL của trình đăng ký Naming.  
public static Remote lookup(String url) throws RemotException, NotBoundException, AccessException, MalformedURLException 
Client lookup để tìm kiếm một đối tượng từ xa gắn liền với tên đối tượng. 
NotBoundException: server ở xa không nhận ra tên của nó.

Naming class - methods
Public static void bind(String url, Remote object) throws RemotException, AlreadyBoundException, MalformedURLException, AccessException 
để liên kết  một tên với một đối tượng ở xa. Nếu thành công thì client có thể tìm kiếm đối tượng stub từ trình đăng ký. 
Có rất nhiều tình huống có thể xảy ra khi gán tên.
MalformedURLException: url không đúng cú pháp. 
RemoteException: không thể liên lạc được với trình đ.ký
AccessException: client không được phép gán các đối tượng trong trình đăng ký. 
AlreadyBoundException: nếu đối tượng URL đã gắn với một đối tượng cục bộ
Naming class - methods
public static void rebind(String url, Remote obj)throws RemoteException, AccessException, MalformedURLException
Phương thức này giống như phương thức bind() ngoại trừ việc là nó gán URL cho đối tượng ngay cả khi URL đã được gán.
Giao tiếp Remote 
Giao tiếp Remote 
Giao tiếp này không khai báo bất kỳ phương thức nào. 
Khai báo một đối tượng được truy xuất từ xa:
RemoteObject class
Giao tiếp Registry
cho phép các client tìm kiếm các đối tượng ở xa trên một server theo tên. 
Các phương thức
Bind() để gán một tên với một đối tượng từ xa cụ thể
List() liệt kê tất cả các tên đã được đăng ký với trình đăng ký
Lookup() tìm một đối tượng từ xa cụ thể với một URL cho trước gắn với nó
Rebind() gán một tên với một đối tượng ở xa khác
Unbind() loại bỏ một tên đã được gán cho một đối tượng ở xa trong trình đăng ký
Registry.REGISTRY_PORT là cổng mặc định để lắng nghe các các yêu cầu. Giá trị mặc định là 1099.

Các bước thiết kế và cài đặt RMI
1. Đặc tả một giao tiếp từ xa (remote interface) trên server.
2. Hiện thực giao tiếp từ xa (remote interface) để Xây dựng một đối tượng từ xa (remote object) .
3. Sinh ra các Stub phía client và Skeleton phía server.
4. Xây dựng chương trình phía Server
5. Xây dựng chương trình phía Client.
6. Khởi động bộ đăng ký RMI (RMI registry)
7. Khởi động các đối tượng từ xa phía server
8. Chạy chương trình phía client.
Ex, Cài đặt chương trinhg  cộng 2 số nguyên
Triệu gọi đối tượng RMI giữa trình khách và đối tượng chủ ở xa
1. Đặc tả một Remote Interface (at Srv)
Các đối tượng trong Remote Inteface phải có khả năng giao tiếp với các đối tượng ở xa (Kế thừa Remote class)
Các phương thức phải có khả năng phát ra ngoại lệ Remote Exception.
// Calculator.java
import java.rmi.*;
public interface Calculator extends Remote
{
public int addNum(int x,int y) throws RemoteException;
}
Biên dịch
2. Hiện thực Remote Interface
Từ giao tiếp RI đã định nghĩa, đối tượng thực sự phải được cài đặt:
 /* CalculatorImpl.java*/
import java.rmi.*;
// extends UnicastRemoteObject 
public class CalculatorImpl implements Calculator {
public int addNum(int x,int y) throws RemoteException {
System.out.println("Client request to calculate");
return (x+y);
}
}
Biên dịch
3. Sinh trung gian Stub và Skeleton
Dựa vào lớp cài đặt CalImpl.class, trình biên dịch rmic.exe của Java sẽ cung cấp hai lớp trung gian
C:\RMI>rmic CalculatorImpl
Kết quả
CalculatorImpl_Stub.class
CalculatorImpl_Skel.class //opt
4. Xây dựng chương trình trên Server
/* CalServer.java*/
public class CalculatorServer{
public static void main(String[] args) throws AlreadyBoundException {
try{
//tao doi tuong Calculator  thuc su
CalculatorImpl c= new CalculatorImpl();
System.out.println("Exporting Calculator ! ");
//thông báo sự hiện diện c là đối tượng có khả năng Remote cho JVM
UnicastRemoteObject.exportObject (c);
//đăng ky doi tuong với trình quản lý rmi
Naming.bind("rmi://localhost/Van",c);
System.out.println("Register Calculator!");
} catch(Exception e) 
{ System.out.println(e); }
   }
}
Biên dịch

5. Xây dựng chương trình trên Client
 Chương trình phía bên máy client có khả năng gọi và sử dụng đối tượng Cal trên máy server:
/* CalculatorClient.java*/
import java.rmi.*;
public class CalculatorClient {
public static void main(String[] args){
try{
System.out.println("Finding Object … ");
// tìm đối tượng cần truy xuất theo tên -> tường minh
Calculator c= (Calculator)Naming.lookup ("rmi://localhost/Van");
// goi phuong thuc cua doi tuong
System.out.println(c.addNum(5,10));
} catch(Exception e) { System.out.println(e); }
  }
}                                          Biên dịch
6. Kích hoạt bộ đăng ký
C:\RMI>rmiregistry.exe
Nó có nhiệm vụ đón nhận (luôn trong trạng thái sẵn sàng phục vụ) các kết nối chứa thông tin về đối tượng do phương thức Naming.bind() gửi đến. 
Mặc định rmiregistry.exe lắng nghe các kết nối gửi đến cổng 1099, có thể chỉ định lại:
C:\RMI>rmiregistry.exe 2012
rmiregistry.exe có trong ..\Java\jdk1.7.0_05\bin
Không cần chạy service trên nếu có: LocateRegistry.createRegistry(1099);
trong main của trình Server

7. K.động các đối tượng phía Server
C:\RMI>java CalculatorServer
Exporting Calculator…
Register Calculator!
Cũng như rmiregistry.exe, sau khi Calculator Server được gọi, hàm Naming.bind() sẽ đi vào vòng lặp vô tận để chờ nhận yêu cầu từ client đến. 
8. Chạy chương trình phía Client
C:\RMI>java CalculatorClient
Finding Object…
15
-> kết quả trả về là lời gọi đến phương thức addNum() của đối tượng CalculatorImpl. 
Quay lại cửa sổ DOS trên Server thấy:
Client request to calculate
-> hàm addNum() đã được gọi thực hiện
Test: RMI_Cal\ (or RMI\Cal - ecls)
Các lớp được tạo ra trong RMI
Các lớp và phạm vi sử dụng

Review
Vận hành RMI trên JVM 
Vận hành RMI trên máy thực
Khi vận hành trên các máy tính vật lý khác nhau cần chú ý về thư viện, security policy.
Tự tạo bộ đăng kí 
Không dùng rmiregistry.exe
Tự tạo bộ đăng kí và tự đăng kí đối tượng: 
Dùng: createRegistry()của lớp LocateRegistry.
Đăng ký một đối tượng khác:

Tìm lớp Stub dựa vào Classpath
Khi Server đăng ký tên đối tượng với rmiregistry, rmiregistry sẽ đi truy tìm lớp trung gian Stub. 
Dựa vào CLASSPATH:
Java dựa vào biến môi trường CLASSPATH để truy tìm các tập tin .class. 
Giá trị mặc định của Classpath là trỏ đến thư mục chứa hiện hành
Nếu CLASSPATH không chỉ or chỉ sai đường dẫn, lỗi xảy ra: ClassNotFoundException: ClassName
Để thay đổi giá trị cho CLASSPATH,  dùng: 
Set Classpath=.;C:\RMI\
Tìm lớp Stub dựa vào tùy chọn Codebase
Codebase (HTML): [CODEBASE = URLDirectory]
Codebase cho phép nạp tự động các lớp Stub từ xa. (khi đăng ký đối tượng với rmiregistry trên máy chủ)
Thực hiện:
máy chủ phải hỗ trợ thêm dịch vụ WebServer chạy trên máy nơi rmiregistry đang chạy . 
chép tập tin (_Stub.class) vào thư mục (myclass) của trình chủ web server.
biến Classpath trên máy ảo nơi rmiregistry đang chạy không được trỏ đến cùng thư mục chứa class (1: classpath, 2: codebase)
Nạp stub từ xa xuống client  thông qua web server
Nạp file từ xa và security policy phía client
Với Java tất cả các thao tác kết nối và chép tập tin lạ từ một máy khác về một máy đều phải thông qua lớp bảo vệ: 
SecurityManager
Khi nạp lớp Stub tự động, chương trình của client cần bổ sung thiết lập lớp phòng vệ:
System.setSecurityManager(new RMISecurityManager()); //sau try{
Nạp file từ xa và security policy phía client
Nạp file từ xa và security policy phía client
Hệ thống phòng vệ RMISecurityManager sẽ cho phép hoặc cấm các kết nối từ xa dựa trên thiết lập trong file: ..\java\jdk1.7.0_05\jre\lib\security\java.policy
Mở tập tin java.policy, edit: 
grant {
permission java.security.AllPermission;
// ko phòng vệ 
permission java.net.SocketPermission "*:1099", "connect, accept, resolve";
// This allows RMI clients to contact the RMIRegistry of any host
};
Chuyển tham số trong RMI
 Đối với việc truyền tham số qua mạng theo cơ chế RMI thì có hai nguyên tắc sau:
Tất cả các kiểu dữ liệu đơn giản như int, char,… đều được truyền theo tham trị.
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 tiếp là Remote hoặc Serializable. 
Các đối tượng cài giao tiếp Remote sẽ được truyền theo tham chiếu 
Các đối tượng cài đặt giao tiếp Serializable sẽ được truyền theo tham trị.
Các đối tượng ko được cài đặt giao tiếp Serializable hay Remote thì ko thể dùng làm tham số truyền qua mạng được
Chuyển đối tượng theo tham trị
Các đối tượng cài đặt giao tiếp Serializable sẽ được truyền theo tham trị
Giao tiếp Serializable dùng cho mục đích báo hiệu: 
Tất cả các lớp đối tượng cài đặt trong giao tiếp Serializable đều có khả năng tuần tự hóa.
Khi gọi một phương thức của đối tượng từ xa, nếu trong lời gọi có y/c tham số kiểu đối tượng:
 đối tượng sẽ được đóng gói và chuyển toàn bộ đến server (nơi tiếp nhận và thực thi phương thức). 
Tại Server, đối tượng được bung ra lại trạng thái ban đầu và được sử dụng
Tuần tự hóa đối tượng
Tuần tự hóa là quá trình chuyển (read/write) tập hợp các thể hiện đối tượng chứa các tham chiếu tới các đối tượng khác thành một luồng byte tuyến tính (tuần tự), 
luồng này có thể được:
 gửi đi qua một Socket, 
lưu vào tệp tin hoặc được 
 xử lý dưới dạng một luồng dữ liệu. 
Việc lưu đối tượng trên đĩa, dữ liệu trên tập tin là loại dữ liệu tuần tự (trải phẳng đối tượng ra theo thứ tự)
Serialization
khả tuần tự hóa
Chỉ có đối tượng thực thi giao diện Serializable mới có thể được ghi lại và được phục hồi bởi các tiện ích tuần tự hóa
một lớp thực thi giao diện Serializable thì lớp đó có khả năng tuần tự hóa->khả tuần tự hóa 
Example Serialization
public class writeObj {
 public static void main(String[] args) throws Exception {
    Junk obj1 = new Junk("Lê Xuân Anh");
    Junk obj2 = new Junk("Lê Quốc Ba");
    ObjectOutputStream objectOut = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("b.txt")));
objectOut.writeObject(obj1); // Write object
    objectOut.writeObject(obj2); // Write object
    objectOut.close(); // Close the output stream
ObjectInputStream objectIn = null;
    int Count = 0;
    Junk object = null;
objectIn = new ObjectInputStream(
new BufferedInputStream(new FileInputStream("b.txt")));
while (Count < 2) {
      object = (Junk) objectIn.readObject(); Count++;
      System.out.println("Object " + Count + ": " + object.toStr());     }
    objectIn.close(); 
  }
}
Ex:  truyền tham số qua mạng sử dụng giao tiếp Serializable
RMI_Ball
1. Tạo lớp đối tượng cài đặt gt Serialization 
2.3. Đặc tả và cài đặt  g.tiếp cho đối tượng trên Server
4. Xây dựng chương trình Client
5. Xây dựng chương trình cho đối tượng Server trên Server
Output
Chuyển đối tượng theo tham chiếu
Khi đối tượng cần chuyển đi quá lớn -> đóng gói chuyển qua mạng sẽ ảnh hưởng tốc độ thực thi ct.
Khi trình chủ có thể tham chiếu và xử lý trực tiếp đối tượng đang nằm trên máy client -> chuyển đối tượng theo tham chiếu từ chủ đến khách -> cơ chế callback.

Thiết kế ct chuyển đổi đối tượng qua mạng theo tham chiếu
Đặc tả giao tiếp cho đối tượng Client
Đặc tả giao tiếp cho đối tượng Server
Cài đặt chi tiết cho đối tượng Client
Cài đặt chi tiết cho đối tượng Server
Xây dựng chương trình cho đối tượng Server trên Server và đăng ký với Registry
Thiết kế chương trình Client gọi phương thức của đối tượng Server
Tạo lớp trung gian cho cả 2 đối tượng Server và CLient
Khởi động rmiregistry
Cài đặt đối tượng trên Server
Chạy trình khách trên Client
1,2. Đặc tả g.tiếp cho đối tượng Client, Server
3.4. Cài đặt chi tiết cho đối tượng Client, Srv 
5. Xây dựng chương trình cho đối tượng Server trên Server và đăng ký với Registry
6. Thiết kế chương trình Client gọi phương thức của đối tượng Server
7. Tạo lớp trung gian cho cả 2 đối tượng Server và Client. 8. Khởi động rmiregistry
9. Cài đặt đối tượng trên Server 10. Chạy trình khách trên Client 
Note
Java cho phép 1 đối tượng có thể cài đặt một lúc nhiều Interface.
Nếu đối tượng cài cả Remote và Serialization thì đối tượng được truyền theo tham chiếu hay tham trị?
Đăng ký nhiều đối tượng với RMIRegistry
Test multiObject
Quản lý nhiều đối tượng với RMIRegistry
Trong java cũng cho phép ta lấy về danh sách các đối tượng mà rmiregistry đang nắm giữ
Factory Object
Khi nhiều đối tượng được tạo ra và được đăng ký với rmiregistry => Hạn chế:
rmiregistry phải quản lý nhiều đối tượng.
Trình khách phải nhớ các tên đối tượng.
Giải pháp: Java cho phép xây dựng:
Một đối tượng được đăng ký rmiregistry và chỉ dùng để tạo ra các đối tượng con khác gọi là Factory object: có thể coi
là xưởng chế tác và cung cấp các đối tượng con cho máy khách
Factory Object là cách thức giao tiếp khá thông dụng, được đưa vào trong EJB của Java

Mô hình hoạt động của Factory Object
Cài đặt ứng dụng Factory Object
Có đối tượng Factory dùng để tạo ra hai đối tượng con: 
FactoryServerImpl:
createNews(): tạo ra đối tượng News khi trình khách gọi
createTimer(): tạo ra đối tượng Timer khi trình khách gọi
NewsImpl
getTodayNews() dùng để lấy về thông tin
TimerImpl. 
getCurrentTime(): dùng để lấy ngày giờ hiên tại trên Server
Mô hình 
Các bước triển khai
Đặc tả giao tiếp và cài đặt đối tượng Timer
Đặc tả giao tiếp và cài đặt đối tượng New
Đặc tả và cài đặt đối tượng FactoryService
Xây dựng trình cài đặt và đăng ký đối tượng FactoryService với rmiregistry
Server_setup: tạo đt FactoryService, đk với rmi
Xây dựng trình khách triệu gọi đối tượng trên máy chủ. Client_Setup:
- liên hệ với đt FactoryService,
- y/c tạo 2 đt News và Timer (createNews, createTimer)
- gọi phương thức của 2 đt (getTodayNews(), getCurrentTime()
Biên dịch và chạy chương trình
Đặc tả g.tiếp cho News, Timer, FactoryService
Cài đặt cho News, Timer
Cài đặt cho FactoryService
Xây dựng trình Server, Client
Output
Static Method Invocation
Cách gọi hàm tĩnh: 
Đối tượng ở xa phải cung cấp lớp giao tiếp của bản thân đối tượng
Trình khách lấy tham chiếu đến đối tượng bằng hàm Naming.lookup().
Trình khách gọi các phương thức của đối tượng chủ. 
Trình khách sẽ dựa vào lớp giao tiếp này để chuyển kiểu đối tượng dạng tường minh (sau khi nhận được) Ex: 
FactoryService objFac= (FactoryService) Naming.lookup("rmi://localhost/Factory");
-> Khi đó có thể truy xuất đối tượng ở xa theo cách thông thường (local)
Dynamic Method Invocation
Nếu không có lớp giao tiếp của đối tượng từ xa:
Không thể chuyển kiểu
Dùng kỹ thuật reflect để triệu gọi phương thức động.
Trình khách lấy tham chiếu đến đối tượng bằng hàm Naming.lookup() dạng tổng quát Object, ex
Object obj= Naming.lookup("rmi://localhost/Obj");
Sau đó, khảo sát đối tượng
Truy tìm xuất xứ class: getclass()
Truy tìm phương thức của đối tượng: getMethod()
Thực thi phương thức bên trong đối tượng: invoke()
Đặc tả và cài đặt một Remote Interface
Xây dựng chương trình trên Server
/* Server_Setup.java*/
public class Server_Setup{
public static void main(String[] args) throws Exception {
//tao doi tuong Calculator  thuc su
Friend f= new FriendImpl();
//thông báo sự hiện diện f là đối tượng có khả năng Remote cho JVM
UnicastRemoteObject.exportObject (f);
System.out.println(“Friend waitting…..");
//đăng ky doi tuong với trình quản lý rmi
Naming.bind("rmi://localhost/Friend",f);
}

 Xây dựng chương trình trên Client
/* Client_Setup.java*/
import java.rmi.*;
import java.lang.reflect.*;
public class Client_Setup {
public static void main(String[] args) throws Exception {
System.out.println("Finding Object … ");
Object f= Naming.lookup ("rmi://localhost/Friend");
// Truy tìm class
Class cls=f.getclass();
Class [] TypeCls = new Class [] {String.class};
Method mthd = f.getMethod(“greeting”, Typecls);
Object [] arg = new Object [] {“Quoc Anh”};
String result = (String) mthd.invoke(f, arg);
System.out.println(result); 
}
  }
RMIRegistry và vấn đề Firewall
Kết nối giữa trình khách và RMIRegistry bị chặn bởi firewall:
Giải pháp
Yêu cầu admin (of firewall) cung cấp 1 số cổng để sử dụng
Sử dụng cơ chế trung gian thông qua cổng 80 của dịch vụ WebServer để truy xuất và gọi đối tượng: cơ chế Tunneling
(cần mô hình lập trình Web services & nghi thức giao tiếp SOAP dựa trên XML)
Tunneling
Web services & SOAP
Web services:
cung cấp cơ chế triệu gọi các đối tượng từ xa thông qua web và giao thức HTTP. 
Cung cấp cơ chế truyền tải định dạng đối tượng theo XML.
 Giao thức SOAP (Simple Object Access Protocol): 
hỗ trợ Web services. 
được định nghĩa dựa trên giao thức HTTP, 
cho phép dữ liệu chuyển đi bằng HTTP và định dạng chuẩn theo XML. 
Các lời gọi hàm, tham số, dữ liệu đều được chuyển thành dạng XML => dễ dàng xử lý bởi bất cứ ngôn ngữ nào 
Lập trình phân tán với CORBA
Khác với RMI:
Các đối tượng được xây dựng trên nền CORBA được áp dụng cho nhiều ngôn ngữ khác nhau.
Bộ phát triển J2SDK cũng hỗ trợ RMI-CORBA, cho phép một đối tượng Java gọi một đối tượng CORBA sử dụng hai cách tiếp cận khác nhau
CORBA (Common Object Request Broker Architecture): kiến trúc môi giới gọi các đối tượng thông dụng -  là ngôn ngữ đặc tả giao tiếp (Interface Definition Language - IDL):
Các đối tượng viết bằng ngôn ngữ khác nhau có thể triệu gọi lẫn nhau theo mô hình đối tượng phân tán
Triệu gọi đối tượng Corba thông qua ORB
Giao tiếp giữa trình khách và đối tượng Corba trên Server
Giao tiếp giữa trình khách và đối tượng Corba trên Server
a. Phần cài đặt đối tượng Corba trên máy chủ:
Đặc tả đối tượng X bằng IDL của Corba
Chuyển đặc tả X thành một ngôn ngữ cụ thể (dùng 1 trình biên dịch tương ứng:
 ex: idlj.exe -> java; idl2cpp.exe-> C++)
Trình biên dịch sẽ tạo ra lớp _Skel
Cài đặt đối tượng băng ngôn ngữ (Java)
b. Phần kết nối với đối tượng khách:
Sử dụng IDL của X y/c trình biên dịch tạo ra _Stub (trình biên dịch tương ưng với trình khách)
Trình khách gọi đối tượng chủ (-> _Stub -> ORB khách -> IIOP -> ORB chủ -> _Skel -> CorbaObject
Ex, hello
Tạo file đặc tả Hello.idl, ex:
interface Hello {
string sayHello(); };
Biên dịch: idlj –fserver Hello.idl
Có 3 file được tạo ra: 
HelloOperation.java: File chuyển đặc tả IDL thành đặc tả interface của Java
Hello.java: File chuyển lớp giao tiếp đối tượng kiểu Java thành lớp giao tiếp đối tượng đặc thù trong Corba
HelloPOA.java: File chứa lớp cài đặt đối tượng Corba
Tạo đối tượng Corba Hello: HelloServant.java
Biên dịch: javac *.java
HelloOperation.class, Hello.class: các lớp trung gian
HelloServant.class: đối tượng corba (kế thừa HelloPOA)

Summary
1. Để xây dựng đối tượng ở xa ta phải:
Thiết lập một giao tiếp của đối tượng. 
Cài đặt giao tiếp của đối tượng, 
Sau đó tạo ra các lớp trung gian _Stub và _Skel tương ứng. 
Giao tiếp ở trình khách với đối tượng chủ thông qua lớp _Stub.
Giao  tiếp của đối tượng chủ với với trình khách thông qua lớp _Skel
Đối tượng chủ phải đăng ký tên với tring rmiRegistry để trình khách có thể truy tìm tham chiếu của đối tượng từ xa (Naming.bind)
Trình  khách truy tìm đối tượng theo tên (Naming.lookup) và gọi phương thức của đối tượng.
2. Chuyển tham số trong RMI:
Truyền dữ liệu giữa trình khách và đối tượng trên máy chủ có thể thông qua tham trị và tham chiếu:
Tham chiếu: các đối tượng phải cài đặt giao tiếp Remote
Tham trị: các đối tượng phải cài đặt giao tiếp Serialization
Tham chiếu từ đối tượng chủ đến đối tượng trên trình khách: tham chiếu ngược
(trình chủ có thể chủ động gọi và điều khiển trình khách)

More about

[LTM] Chương 8.1: Network Program with Java-TCP

Người đăng: share-nhungdieuhay on Thứ Tư, 9 tháng 4, 2014


Objectives

  • Giao tiếp Socket
  • Đặc điểm, cấu trúc Socket
  • TCP Socket
  • UDP Socket 
  • Thiết kế giải thuật server/client
  • Các lớp trong gói java.net 
  • Ứng dụng client/server qua TCP socket 
  • Ứng dụng client/server qua UDP socket 



Giới thiệu

  • Trong quá trình truyền tin có thể xảy ra nhiều sự cố:
  • một hay nhiều gói bị mất hay bị hỏng 
  • cần phải truyền lại hay không hoặc 
  • các gói tin đến không theo đúng trình tự. 
  • Cần xử lý;
  • việc phân chia dữ liệu thành các gói, 
  • tạo các header, phân tích header của các gói đến, 
  • quản lý danh sách các gói đã nhận được/ chưa nhận được…
  • => nhiều công việc cần phải thực hiện, và đòi hỏi rất nhiều phần mềm phức tạp để xử lý.
  • => Socket

  • Socket API – Socket Application Programming Interface: 
  • là một cuộc cách mạng của Berkeley UNIX. 
  • được giới thiệu ở BSD4.1 UNIX, 1981 
  • Xuất phát từ ý tưởng quan trọng nhất của UNIX: 
  • tất cả các thao tác vào/ra giống như vào ra tệp tin 
  • Socket xem một liên kết mạng như là một luồng mà có thể đọc dữ liệu ra hay ghi dữ liệu vào từ luồng này. 
  • Nó che dấu người lập trình khỏi các chi tiết mức thấp của mạng như môi kiểu đường truyền, các kích thước gói, yêu cầu truyền lại gói, các địa chỉ mạng... 


KHÁI NIỆM VỀ SOCKET

  • Socket: “cơ chế ổ cắm”
  • Các máy có khả năng kết nối được với nhau.
  • Dùng cơ chế client/server
  • Cung cấp hai dịch vụ chính chuyển dữ liệu thông qua socket API:
  • unreliable datagram (UDP)
  • reliable, byte stream-oriented (TCP)

Socket trong TCP/IP Model



Socket

  • socket được định nghĩa trong hệ điều hành bằng một cấu trúc, được xem như điểm nối để hai procceses giao tiếp với nhau.
  • Cấu trúc socket gồm 5 fields:


  1. Family : xác định protocol group
  2. Type : xác loại socket, stream, datagram hay raw socket.
  3. Protocol : kieu gthuc. thường gán giá trị bằng 0
  4. Local Socket Address và 
  5. Remote Socket Address : là địa chỉ socket của process cục bộ và từ xa.

Cấu trúc socket

Địa chỉ của một socket
Địa chỉ của một socket trên mạng TCP/IP gồm có hai phần:

  • Địa chỉ IP: một số nguyên 32 bits xác định duy nhất một card mạng trên máy tính (host)
  • Cổng dịch vụ: một số nguyên 16 bits xác định điểm kết nối với một ứng dụng trên một host. 
  • Các ứng dụng thương mại hay các dịch vụ thông dụng sử dụng các cổng dịch vụ chuẩn đã được đăng ký


Cấu trúc địa chỉ socket
struct sockaddr_in
{
u_char sin_len;
u_short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};

Các hàm socket (in System Calls Interface ) 


  1. Hàm socket() để tạo mới một socket
  2. Hàm bind() Đăng ký socket đã khởi tạo với địa chỉ socket local. Trả về 0 nếu thành công, -1: thất bại.
  3. Hàm connect() để client kết nối đến server
  4. Hàm listen() đặt socket ở trạng thái chờ, lắng nghe kết nối từ phía client
  5. Hàm accept() : chấp nhận kết nối từ client đến
  6. Hàm read() để đọc dữ liệu từ socket vào bộ nhớ
  7. Hàm write() để ghi dữ liệu từ bộ nhớ -> socket
  8. Hàm sendto() để gởi dữ liệu đến một socket từ xa
  9. Hàm recvfrom(): nhận dữ liệu đến từ 1 socket từ xa


Các loại Socket

  1. Stream Socket: dùng cho connection-oriented protocol như TCP.
  2. Datagram Socket: dùng cho connectionless protocol như UDP.
  3. Raw Socket: dùng cho một số protocol của một số ứng dụng đặc biệt, dùng các dịch vụ trực tiếp của lớp IP.

TCP socket – đặc điểm

  1. Có thể sử dụng để liên lạc theo mô hình client/server
  2. Có 1 đường kết nối ảo giữa 2 phía Server/client
  3. Một trong 2 phía phải đợi tiến trình kia yêu cầu kết nối
  • Server lắng nghe và chấp nhận yêu cầu kết nối
  • Mỗi thông điệp gửi đều có xác nhận trở về
  • Các gói tin chuyển đi tuần tự

TCP socket – hoạt động

  • Client phải kết nối đến server 
  • server process phải chạy trước (phần tử thụ động)
  • server phải tạo một socket để lắng nghe và chấp nhận các kết nối từ client
  • Client kết nối đến server bằng cách:
  • Khởi tạo TCP socket ở local
  • Xác định IP address, port number của server process và kết nối đến
  • Sau khi client khởi tạo socket, nó sẽ thiết lập kết nối đến server
  • Khi server nhận yêu cầu kết nối, nó sẽ chấp nhận yêu cầu và khởi tạo socket mới để giao tiếp với client.
  • Cho phép server chấp nhận nhiều client tại một thời điểm.

TCP socket - hoạt động

UDP socket – đặc điểm

  1. Cung cấp cơ chế truyền không tin cậy các nhóm  bytes (datagrams) giữa client và server.
  2. Không cần thiết lập kết nối giữa client với server.
  3. Client phải gởi kèm địa chỉ IP và port đích
  4. Server khi nhận dữ liệu sẽ phân tích địa chỉ của client để truyền lại.

--

  • Thông điệp có thể gửi nhiều lần
  • Người gửi không chắc chắn thông điệp tới người nhận
  • Thông điệp sau có thể đến đích trước thông điệp gửi trước nó


UDP socket – hoạt động

Số hiệu cổng của socket

  • Một trong 2 quá trình phải công bố số hiệu cổng của socket mà mình sử dụng
  • Mỗi cổng giao tiếp thể hiện 1 địa chỉ xác định trong hệ thống
  • Có thể nhận dữ liệu gửi đến cổng giao tiếp này từ các quá trình khác.

Viết các ứng dụng Socket

  • Thiết kế giải thuật cho client/Server.
  • Công cụ viết
  • Dùng các class trong Java
  • Example


Thiết kế giải thuật cho client/Server

  • Giải thuật cho chương trình client/Server dùng TCP
  • Giải thuật cho chương trình client/Server dùng UDP
  • Chương trình server có hai loại: 

        1. Lặp (iterative)
        2. Đồng thời (concurrent).

  •  Hai dạng giao thức chương trình server: 

       1.Connection-oriented  (TCP)
       2.Connectionless. (UDP)

Giải thuật cho client/Server TCP
 Client

  1. Xác định địa chỉ server.
  2. Tạo socket.
  3. Kết nối đến Server
  4. Gởi/nhận dữ liệu theo giao thức đã thiết kế.
  5. Đóng socket.

Server

  1. Tạo socket 
  2. Đăng ký với hệ thống
  3. Lắng nghe kết nối
  4. Chấp nhận kết nối 
  5. Gửi nhận dữ liệu theo đúng giao thức đã thiết kế.
  6. Đóng  kết nối sau khi đã hoàn thành và trở lại trạng thái lắng nghe chờ kết nối mới


Giải thuật cho client/Server UDP
 Client

  1. Xác định địa chỉ server.
  2. Tạo socket.
  3. Gởi/nhận dữ liệu theo giao thức đã thiết kế.
  4. Đóng socket.

Server

  1. Tạo socket 
  2. Đăng ký với hệ thống
  3. Lặp công việc đọc dữ liệu từ client gửi đến và gửi trả kết quả cho client theo đúng giao thức lớp ứng dụng đã thiết kế.
  4. Đóng Socket


Thiết kế giải thuật cho Server – concurrent, connection-oriented (TCP)

  • Tạo socket và đăng ký với hệ thống
  • Đặt socket ở chế độ chờ, lắng nghe kết nối.
  • Khi có request từ client, Server sẽ:
  • chấp nhận kết nối, 
  • tạo một process con để xử lý. 
  • Quay lại trạng thái chờ, lắng nghe kết nối mới
  • Công việc của process con:
  • Nhận thông tin kết nối của client
  • Giao tiếp với client theo giao thức lớp ứng dụng đã thiết kế
  • Đóng kết nối và kết thúc process con.
  • Đóng socket

Thiết kế giải thuật cho Server – concurrent, connectionless (UDP) 

  • Tạo socket và đăng ký với hệ thống
  • Lặp công việc nhận dữ liệu từ client, đối với một dữ liệu nhận:
  • tạo mới một process để xử lý. 
  • Tiếp tục nhận dữ liệu mới từ client
  • Công việc của process mới:
  • Nhận thông tin của process cha chuyển đến, lấy thông tin socket
  • Xử lý và gửi thông tin về cho client theo giao thức lớp ứng dụng đã thiết kế
  • Kết thúc

Thiết kế giải thuật server – multi-protocol Server (TCP/UDP)

  • Dùng một chương trình, mở một master socket cho cả TCP và UDP.
  • Dùng hàm hệ thống (select) để chọn lựa TCP socket hay UDP socket sẵn sàng.
  • Tùy vào protocol (TCP, UDP) để xử lý gửi nhận thông điệp theo đúng giao thức của lớp ứng dụng
  • Ref RFC 1060

Lập trình mạng trên Java
Gói java.net cung cấp các lớp

  1.  InetAddress
  2. URL
  3.  URLConnection
  4.  ServerSocket
  5.  Socket
  6. DatagramSocket
  7. DatagramPacket
InetAddress class


  • Phục vụ việc quản lý địa chỉ theo IP và tên.
  • Cung cấp các phương thức thông dụng nhất dùng để chuyển đổi và truy xuất IP 
  • Nó bao gồm hai trường thông tin: (không thể truy xất chúng trực tiếp)
  • hostName (một đối tượng kiểu String) và 
  • address (một số kiểu int). 
  • Lớp InetAddress không có các constructor cho lớp InetAddress
  • Có các phương thức:

Tất cả các phương thức này đều thực hiện kết nối tới server DNS cục bộ để biết được các thông tin trong đối tượng InetAddress:
1. public static InetAddess getLocalHost()throws UnknownHostExceptiongetByName 
Trả về InetAddress là IP của local
2. public static InetAddess getByName(String hostname) throws UnknownHostException: 
Nhận tên host và trả về InetAddress (name và IP address)
3. public static InetAddess [] getAllByName (String hostname) throws UnknownHostException
Nhận địa chỉ host dạng String và trả về tất cả InetAddress tương ứng với host (name và IP address)



  • Nhận các trường thông tin của một đối tượng InetAddress: 
  • Chỉ có các lớp trong gói java.net có quyền truy xuất tới các trường của lớp InetAddress. bằng các phương thức:


public byte[] getAddress()
Trả về một địa chỉ IP dưới dạng một mảng các byte.
public String getHostAddress()
Trả về một địa chỉ IP dưới dạng String "%d.%d.%d.%d"
public String getHostName()
Trả về một xâu biểu diễn hostname của một đối tượng InetAddress. Nếu máy không có hostname, thì sẽ trả về "%d.%d.%d.%d"



Ex:  In địa chỉ IP và name  củalocalhost
import java.net.*;
public class HostInfo {
public static void main(String args[]) {
try {
InetAddress myHost = InetAddress.getLocalHost(); System.out.println(myHost.getHostAddress());
System.out.println(myHost.getHostName());
} catch (UnknownHostException ex) {
System.err.println("Cannot find local host");}
}
}

Ex: In IP của www.google.com
import java.net.*; 
class Print_IP{ 
public static void main (String args[]) { 
try { 
InetAddress[] addresses = 
InetAddress.getAllByName("www.google.com"); 
for (int i = 0; i < addresses.length; i++) { 
System.out.println(addresses[i]); 

} catch (UnknownHostException e) { 
System.out.println("Could not find www.google.edu.vn"); 

     } 
}



URL  

  • URL(Uniform Resource Locator)  là địa chỉ định vị tài nguyên trên mạng, 
  • Một URL  thường bao gồm 3 phần: 
  1. Protocol
  2. Hostname
  3. Filename. 
  4. (port)
  • Java đóng gói tất cả vào một lớp URL. 
  • Đối tượng URL được tạo ra bằng một trong những phương thức khởi tạo sau:

URL  class - Constructors
public URL(String spec) throws MalformedURLException 
Tạo một đối tượng URL từ địa chỉ định vị là một chuỗi. (simple)
public URL(String pro, String host, int port, String file) throws MalformedURLException 
Tạo một địa chỉ định vị tuyệt đối với đầy đủ nghi thức(protocol), máy chủ(server), cổng(port), đường dẫn(file) tới tập tin cần lấy trên máy chủ. 
public URL(String protocol, String host, String file) throws MalformedURLException 
Tạo một  địa chỉ  định vị tuyệt  đối với  đầy  đủ protoccol, server, path file 

Phân tích một URL thành các thành phần

public final Object getContent() throws IOException :lấy về nội dung mà kết nối theo địa chỉ URL có được.
String getFile() :Lấy về tên tập tin hay tài liệu nằm trong chuỗi địa chỉ URL có được. 
String getHost() :Lấy tên máy chủ (thường là thành phần thức 2 của chuỗi URL) 
String getPort() :Lấy về số hiệu cổng. 
String getProtocol() :Lấy về tên giao thức(thường là thành phần đầu tiên trong chuỗi URL) 
String getRef() :Lấy về nội dung chuỗi tham khảo thêm trong chuỗi URL (được đặt sau dấu #  của chuỗi) 
URL class - ex
import java.net.*;
import java.io.*;

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

        URL aURL = new URL("http://google.com:80/docs/books/tutorial"
                           + "/index.html?name=networking#DOWNLOADING");

        System.out.println("protocol = " + aURL.getProtocol());
        System.out.println("authority = " + aURL.getAuthority());
        System.out.println("host = " + aURL.getHost());
        System.out.println("port = " + aURL.getPort());
        System.out.println("path = " + aURL.getPath());
        System.out.println("query = " + aURL.getQuery());
        System.out.println("filename = " + aURL.getFile());
        System.out.println("ref = " + aURL.getRef());
    }
}

Tìm kiếm dữ liệu từ một URL
public final InputStream openStream() throws IOException: 
kết nối tới một tài nguyên được tham chiếu bởi một URL, thực hiện mở luồng nhập để đọc thông tin trả về từ máy chủ  
public URLConnection openConnection() throws java.io.IOException: 
Mở một socket tới một URL xác định và trả về một đối tượng URL. 
public final Object getContent() throws java.io.IOException: 
Cung cấp cách tải dữ liệu được tham chiếu bởi một URL

URL class: ex get text
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
public class getText {
  public static void main(String[] argv) throws Exception {
    URL url = new URL("http://tintuconline.com.vn/vn/index.html");
    BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
    String str;
    while ((str = in.readLine()) != null) {
      System.out.println(str); 
    }
    in.close();
  }
}
URLConnection class

  • URLConnection là một lớp trừu tượng biểu diễn một liên kết tích cực tới một tài nguyên được xác định bởi 1 URL. 
  • Ý nghĩa của lớp URLConnection:
  • Cung cấp nhiều khả năng điều khiển hơn thông qua việc tương tác với một server chứ không phải lớp URL: 
  • kiểm tra các headerMIME được gửi bởi một Http Server. 
  • tải về các tệp nhị phân. 
  • gửi dữ liệu trở lại Web server bằng lệnh POST. 
  • Là một phần của cơ chế quản trị giao thức
  • phân tích các chi tiết xử lý một giao thức với việc xử lý các kiểu dữ liệu cụ thể, 
  • cung cấp các giao diện người dùng, và thực hiện các công việc khác mà một trình duyệt thường làm.

Mở các URLConnection  
Một chương trình sử dụng lớp URLConnection trực tiếp theo một dãy các bước cơ bản sau:

  • Xây dựng một đối tượng URL. 
  • Gọi phương thức openConnection() của đối tượng URL để tìm kiếm một đối tượng URLConnection cho URL đó. 
  • Cấu hình đối tượng URL. 
  • Đọc các trường header. 
  • Nhận một luồng nhập và đọc dữ liệu. 
  • Nhận một luồng xuất và ghi dữ liệu. 
  • Đóng liên kết. 

Ex, xây dựng 1 URLConnection 
u= new URL("http://www.microsoft.com"); 
URLConnection uc; 
uc=u.openConnection();
Methods: read/write data 
public Object getContent() throws IOException 
chỉ làm việc khi Java có một trình quản lý nội dung cho kiểu nội dung. tải về đối tượng được chọn bởi URL của URLConnection này.
public InputStream getInputStream()  
luồng này cho phép tự đọc và phân tích dữ liệu.
public OutputStream getOutputStream() 
ghi dữ liệu vào một URLConnection. Trả về một luồng OutputStream trên đó có thể ghi dữ liệu để truyền tới một server.
Phải gọi phương thức setDoOutput() trước khi yêu cầu một luồng xuất. (URLCon. ko cho phép xuất default)

Đọc dữ liệu từ một server

Các bước tối thiểu cần để tìm kiếm dữ liệu từ một URL bằng cách sử dụng đối tượng URLConnection:
Bước 1: Xây dựng một đối tượng URL.
Bước 2: Gọi phương thức openConnection() của lớp URL để tìm kiếm một đối tượng URL Connection cho đối tượng URL đó.
Bước 3: Gọi phương thức getInputStream().
Bước 4: Đọc từ luồng nhập bằng cách sử dụng API.
Ex, get source web hcmute.edu.vn
import java.net.*; 
import java.io.*; 
public class  getText { 
 public static void main(String[] args) throws MalformedURLException { 
  String thisLine; 
  URL u; 
  URLConnection uc; 
    u =new URL("http://www.hcmute.edu.vn"); 
    try{ 
     uc=u.openConnection(); 
     DataInputStream theHtml = new DataInputStream(uc.getInputStream()); 
     try{ 
     while((thisLine=theHtml.readLine())!=null) 
                System.out.println(thisLine); 
            } catch(Exception e)    { 
         System.err.println(e); } 
       }        catch(Exception e)    { 
       System.err.println(e);   } 
    }  
 }
Ex: send data to server
try{ 
   URL u = new URL(http://www.hcmute.edu.vn); 
   URLConnection uc = u.openConnection(); 
   uc.setDoOutput(true); 
    DataOutputStream dos = new DataOutputStream(uc.getOutputStream()); 
  dos.writeByte(“Here is some data”); 
}  catch(Exception e)  { 
System.err.println(e); 


Phân tích Header

HTTP Server cung cấp một số lượng thông tin đáng kể trong các header MIME trước mỗi đáp ứng.
Thông tin trong các header MIME có thể:

  • cơ chế mã hóa nội dung được sử dụng, 
  • chiều dài của nội dung được trả về bằng byte
  • ngày và giờ truy nhập cuối 
  • ngày hết hạn của nội dung, 
  • ngày mà nội dung được sửa đổi lần cuối. 

Có thể truy vấn một URLConnection để tìm ra thông tin MIME nào mà server đã cung cấp.
Ngoài HTTP, rất ít giao thức sử dụng các header MIME.

Methods

public String getContentType() 
trả về kiểu nội dung MIME của dữ liệu. Nó phụ thuộc vào web server gửi một header MIME tương ứng. Các kiểu nội dung phổ biến khác bao gồm: text/plain, image/gif, image/jpeg.
public int getContentLength() 
cho biết nội dung có kích thước bao nhiêu byte.
public String getContentEncoding() 
trả về String cho ta biết cách thức mã hóa. Nếu nội dung được gửi không được mã hóa (như trong trường hợp của HTTP server),
public long getDate() 
trả về một số nguyên kiểu long cho bạn biết tài liệu đã được gửi khi nào. Ta có thể chuyển đổi nó sang một đối tượng kiểu java.util.Date.
public long getExpiration() 
public long getLastModified() 
URL class - ex
public class GetURLInfor {
public static void printinfo(URL url) throws IOException {
    URLConnection c = url.openConnection(); // Get URLConnection from URL
    c.connect(); // Open a connection to URL
    System.out.println("  Content Type: " + c.getContentType());
    System.out.println("  Content Encoding: " + c.getContentEncoding());
    System.out.println("  Content Length: " + c.getContentLength());
    System.out.println("  Date: " + new Date(c.getDate()));
if (c instanceof HttpURLConnection) {
      HttpURLConnection h = (HttpURLConnection) c;
      System.out.println("  Request Method: " + h.getRequestMethod());
      System.out.println("  Response Message: " + h.getResponseMessage());
      System.out.println("  Response Code: " + h.getResponseCode());    }
  }
 public static void main(String[] args) {
    try {
      printinfo(new URL(args[0]));
    } catch (Exception e) {      System.err.println(e + " Not found URL");
      System.err.println("Usage: java GetURLInfo <url>");     }
  }
}

Socket trong Java
Java cung cấp lớp (trong thư viện java.net)

  •  ServerSocket  (thường dùng cho server) và
  •  Socket  (thường dùng cho  client) có thể được sử dụng cho server
  • Có các phương thức tương ứng với các thao tác của  server và client 

Socket class
Dùng để tạo kết nối từ phía client tới Server
Các phương thức hỗ trợ:

  • Tạo Socket
  • Nhận thông tin từ Socket
  • Lấy các thông tin về Socket dạng Stream
  • Đóng Socket
  • Đóng luồng nhập/xuất từ SOcket


Tạo Socket
Các phương thức tạo Socket:
1. public Socket(String host, int port) throws UnknownHostException, IOException: 
Tạo 1 socket TCP với host và port x/đ
2. public Socket(InetAddress address, int port) throws IOException: 
Tạo 1 socket TCP với 1 host có address được x/đ bởi 1 object InetAddress  và port x/đ


3. public Socket(InetAddress address, int port, InetAddress interface, int localPort) throws IOException, UnknownHostException: Socket tao ra kết nối tới host ở xa thông qua một giao tiếp mạng và số hiệu cổng cục bộ
4. public Socket(String host, int port, InetAddress interface, int localPort) throws IOException, UnknownHostException
5. public Socket(String host, int port, boolean stream): stream qui định kiểu kết nối (T/F)
Nhận các thông tin về Socket
InetAddress getInetAddress() :
trả về địa chỉ (IP và hostname) của host mà socket  kết nối đến.
int getPort() :
trả về port của host mà socket kết nối đến.
InetAddress getLocalAddress() : 
trả về địa chỉ của host cục bộ.
int getLocalPort() : 
trả về port trên host cục bộ.

Ex:Kết nối đến 1 số web server

import java.net.*;
import java.io.*;
public class getSocketInfo {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
try {
Socket Sk = new Socket(args[i], 80);
System.out.println( "From port " + Sk.getLocalPort() + " of " + Sk.getLocalAddress());
System.out.println("Connected to " + Sk.getInetAddress() + " on port " + Sk.getPort());
} catch (UnknownHostException e) {
System.err.println("I can't find " + args[i]);
} catch (SocketException e) {
System.err.println("Could not connect to " + args[i]);
} catch (IOException e) {
System.err.println(e); }
} // end for
  } // end main
} // end getSocketInfo


Đọc /ghi dữ liệu với Socket dạng Stream
Việc nhận dữ liệu /ghi dữ liệu với socket được tiến hành thông qua luồng

Các phương  thức truy xuất luồng dữ liệu nhập/xuất

public OutputStream getOutputStream() throws IOException
Trả về một output stream cho việc ghi (các byte) dữ liệu từ ứng dụng đến một socket.
public InputStream getInputStream() throws IOException
Trả về một input stream cho việc đọc (các byte) dữ liệu từ một socket  vào chương trình.
Ex, Lấy các thông tin về Socket dạng Stream
Socket clientSk = new Socket("localhost", 9999);
//Tạo luồng đọc vào từ bàn phím
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader(System.in));
//Tạo luồng để ghi dữ liệu từ client đến server(sk)
DataOutputStream outToServer =
New DataOutputStream(clientSk.getOutputStream());
//Hoac PrintWriter, dung println() de ghi
PrintWriter outToServer = new PrintWriter(new BufferedWriter(new OutputStreamWriter( clientSk.getOutputStream())), true);

// Tạo luồng để đọc dữ liệu từ server(sk) gửi về client
BufferedReader inFromServer = new BufferedReader( new
InputStreamReader(clientSk.getInputStream()));

Đóng Socket 

Phương thức:
public void close() throws IOException 
Khi một Socket đã bị đóng lại:

  • Có thể truy xuất tới các trường thông tin qua các phương thức: getInetAddress(), getPort(), getLocalHost(), và getLocalPort(). 
  • Dùng phương thức getInputStream() hoặc getOutputStream() thì ngoại lệ IOException được đưa ra. 

Đóng luồng nhập/ xuất
Đóng luồng nhập/ xuất từ socket:

  • public void shutdownInput() throws IOException 
  • public void shutdownOutput() throws IOException 

Các phương thức này không thực sự ngắt liên kết. Tuy nhiên, nó chỉ điều chỉnh luồng kết nối tới nó
Kiểm tra các luồng nhập và luồng xuất mở hay đóng

  • public boolean isInputShutdown() 
  • public boolean isOutputShutdown() 

ServerSocket class
Lớp ServerSocket:

  • các constructor để tạo các đối tượng ServerSocket mới, 
  • các phương thức để lắng nghe các liên kết trên một cổng xác định, và 
  • các phương thức trả về một Socket khi liên kết được thiết lập, 

=> có thể gửi và nhận dữ liệu.

Server – Hoạt động

1. Một ServerSocket mới được tạo ra trên một cổng xác định bằng cách sử dụng một constructor ServerSocket.
2. ServerSocket lắng nghe liên kết đến trên cổng đó bằng cách sử dụng phương thức accept().
Phương thức accept() phong tỏa cho tới khi một client thực hiện một liên kết, phương thức accept() trả về một đối tượng Socket mà liên kết giữa client và server.
3. Tùy thuộc vào kiểu server, hoặc phương thức getInputStream(),
getOutputStream() hoặc cả hai được gọi để nhận các luồng vào ra để truyền tin với client.
4. server và client tương tác theo một giao thức thỏa thuận sẵn cho tới khi ngắt liên kết.
5. Server, client hoặc cả hai ngắt liên kết
6. Server trở về bước hai và đợi liên kết tiếp theo.

Tạo Socket cho Server

public ServerSocket(int port) throws IOException, BindException 
Tạo một socket cho server trên cổng xác định.
Nếu port = 0, hệ thống chọn một cổng ngẫu nhiên.khó x/đ
public ServerSocket(int port, int queuelength, InetAddress bindAddress) throws IOException  
Tạo một đối tượng ServerSocket trên port xác định với queuelength xác định. ServerSocket chỉ gán cho địa chỉ IP cục bộ bindAddress xác định.
Constructor này hữu ích cho các server chạy trên các hệ thống có nhiều địa chỉ IP
ex
public class portSrv  { 
 public static void main(String[] args)   { 
for(int i=0;i<=1024;i++)   { 
   try{ 
 ServerSocket ss= new ServerSocket(i); 
    ss.close(); 
   
   catch(IOException e)    { 
   System.out.print("Co 1 server tren cong "+i); 
   
 
  } 
}
Chấp nhận và ngắt liên kết 
Socket accept() throws IOException :
Lắng nghe một kết nối đến socket này và chấp nhận nó.
nó dừng quá trình xử lý và đợi cho tới khi client được kết nối
void close() throws IOException : Đóng socket.
Ta sử dụng các phương thức getInputStream() và getOutputStream() để truyền tin với client.
Methods
Các phương thức trong ServerSocket

  • InetAddress getInetAddress() : trả về địa chỉ của socketserver
  • int getLocalPort() : Trả về port mà server đang lắng nghe. 
  • void setSoTimeout(int timeout) throws SocketException
  • Enable/disable SO_TIMEOUT với khai báo timeout (milliseconds)

Ex: DateTime Server
import java.net.*; 
import java.io.*; 
class ScanPort  { 
 public static void main(String[] args)   { 
   try{ 
   ServerSocket theServer = new ServerSocket(5776); 
while(true) { 
  Socket con = theServer.accept(); 
  PrintStream p = new PrintStream(con.getOutputStream()); 
  p.println(“Connected to this Server "); 
  con.close(); 

} catch(IOException e) { 
  System.err.println(e); 



Tương tác giữa client/server qua socket TCP

Lập trình Socket cho giao thức TCP 

  • Cấu trúc chương trình Client
  • Cấu trúc chương trình Server



Cấu trúc chương trình client

Cấu trúc chương trình server

Ex: viết ứng dụng client/ server bằng TCP Socket
1) client đọc các dòng văn bản do người dùng gõ từ bàn phím (inFromUser stream) , gửi tới server qua socket (outToServer stream)
2) server đọc các dòng gửi từ socket
3) server chuyển sang chữ hoa và gửi trả lại cho client
4) client đọc và in lại dòng văn bản nhận được từ socket (inFromServer stream)
TCP client
class TCPClient_upcase { 
public static void main(String argv[]) throws Exception { 
String sentence; 
String modifiedSentence;
Socket clientSocket = new Socket("localhost", 9999); //Create Socket
//Create inputStream for reading data from keyboard
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); 
sentence = inFromUser.readLine();
// Create OutputStream for writing byte to Server socket
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
outToServer.writeBytes(sentence + '\n');
// Create inputStream for reading data from Serversocket
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 
modifiedSentence = inFromServer.readLine(); 
//View data that received from server
System.out.println("FROM SERVER: " + modifiedSentence);
clientSocket.close(); 

}
TCP Server
class TCPServer_upcase { 
public static void main(String argv[]) throws Exception { 
String clientSentence; 
String upSentence;
System.out.println("Hello, wellcome to Server. Waiting.... ");
ServerSocket welcomeSocket = new ServerSocket(9999); //Create Server Socket
while(true) { 
//Create connection
Socket connectionSocket = welcomeSocket.accept();
//Create InputStream for reading data from socket client
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
clientSentence = inFromClient.readLine();
// Create OutputStream for writing data to socket client
DataOutputStream  outToClient = new DataOutputStream(connectionSocket.getOutputStream());
//Process: upcase
upSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(upSentence); 
System.out.println("Done!!!"); } 
}
}
output
D:\Practice_Java\TCP-UDP\bin




Using GUI in TCP Socket



Exercise: Print Primes
TCPSever_SNT, TCPClient_SNT
MultiThread trong các chương trình Server
Đa tuyến hay được ứng dụng trong các chương trình Server:

  • cho phép các server làm việc với nhiều client đồng thời. 
  • Server này được gọi là server tương tranh (concurrent server):
  • server tạo ra một tuyến đoạn để quản lý từng yêu cầu, 
  • sau đó tiếp tục lắng nghe các client khácMô  hình

Example
Thread_TCPServer.java
  Thread_TCPClient.java
Sample:Chuoi, Server, Client (Object)
Prime: (Object: int+ Str)
Array_Object (Socket+Object)
MultiServer: (MultiSrv, cuoiky.cuoiky)
Str_Client_Loop,
Str_Server1_Loop,
Str_Server2_Loop



I/O Stream in Read/ write from/to socket
DataOutputStream : dùng
- writeBytes(str) để ghi string;
- writeInt(num) để ghi số (với all dữ liệu nguyên thủy)…
DataInputStream:
- readLine(): để đọc string
- readInt(num) để đọc số (với all dữ liệu nguyên thủy)…
PrintWriter: dùng
- println(str) de ghi string
InputStreamReader: dùng read(char []) để đọc vào mảng char. Sau đó in char[] (or->String)
BufferredReader: dùng readLine(): để đọc string
ObjectI/Ostream: Object: serializable

More about

[LTM] Chương 6 : Java Threads

Người đăng: share-nhungdieuhay on Thứ Tư, 26 tháng 3, 2014

More about