ChjpCoj

ChjpCoj

Subscribe to RSS feed

Giới thiệu Java


Java là một công nghệ xây dựng các ứng dụng phần mềm có vị trí rất lớn trong những năm cuối thế kỉ 20, đầu thế kỉ 21. Nó được coi là công nghệ mang tính cách mạng và khả thi nhất trong việc tạo ra các ứng dụng có khả năng chạy thống nhất trên nhiều nền tảng mà chỉ cần biên dịch một lần.


Lần đầu tiên xuất hiện vào năm 1992 như là một ngôn ngữ dùng trong nội bộ tập đoàn Sun Microsystems để xây dựng ứng dụng điều khiển các bộ xử lý bên trong máy điện thoại cầm tay, lò vi sóng, các thiết bị điện tử dân dụng khác. Không chỉ là một ngôn ngữ, Java còn là một nền tảng phát triển và triển khai ứng dụng trong đó máy ảo Java, bộ thông dịch có vai trò trung tâm.

Sun, công ty đã phát minh ra ngôn ngữ Java, chính thức ban hành bản Java Development Kit 1.0 vào năm 1996 hoàn toàn miễn phíđể các nhà phát triển có thể tải về, học Java, xây dựng các ứng dụng Java và triển khai chúng trên các hệ điều hành có hỗ trợ Java. Ban đầu, Java chủ yếu dùng để phát triển các applet, các ứng dụng nhúng vào trình duyệt, góp phần làm sinh động các trang web tĩnh vốn hết sức tẻ nhạt hồi dó. Tuy nhiên, cùng với sự phát triển của công nghệ thông tin và nhu cầu của xã hội, Java applet đã dần mất đi vị trí của nó và thay vào đó, các công ty, cộng đồng ủng hộ Java đã phát triển nó theo một hướng khác. Hiện nay, công nghệ Java được chia làm ba bộ phận:

J2SE
Gồm các đặc tả, công cụ, API của nhân Java giúp phát triển các ứng dụng trên desktop và định nghĩa các phần thuộc nhân của Java.
J2EE
Gồm các đặc tả, công cụ, API mở rộng J2SE để phát triển các ứng dụng qui mô xí nghiệp, chủ yếu để chạy trên máy chủ (server). Bộ phận hay được nhắc đến nhất của công nghệ này là công nghệ Servlet/JSP: sử dụng Java để làm các ứng dụng web.
J2ME
Gồm các đặc tả, công cụ, API mở rộng để phát triển các ứng dụng Java chạy trên điện thoại di động, thẻ thông minh, thiết bị điện tử cầm tay, robo và những ứng dụng điện tử khác
Java đã trải qua 3 bước phát triển quan trọng: Java 1.0 gắn liền với bản JDK đầu tiên, Java 2 gắn với JDK 1.2 và Java 5 gắn với J2SDK 1.5

Ngày nay, khi nhắc đến Java người ta không còn chỉ nhắc đến Java như là một ngôn ngữ mà nhắc đến Java như là một công nghệ hay một nền tảng phát triển. Nó bao gồm các bộ phận:

Máy ảo Java: JVM
Bộ công cụ phát triển: J2SDK
Các đặc tả chi tiết kĩ thuật (specifications)
Ngôn ngữ lập trình (programming language)

Nguồn
http://www.itgatevn.com.vn

Thao tác với các tệp dữ liệu với bằng Java

Java cung cấp một giao lập trình ứng dụng (API) chuẩn hoá, đơn giản để thực hiện các thao tác đọc/ghi tới như file, database và socket - API I/O. Bài này sẽ hướng dẫn bạn cách tiếp cận có hiệu quả trong việc đọc một lượng dữ liệu lớn trong trường hợp cần phải cân nhắc kỹ các các yếu tố như thời gian và cấp phát bộ nhớ để cải thiện hiệu nǎng tổng thể của hệ thống.

Bài này sẽ hướng dẫn bạn cách tiếp cận có hiệu quả trong việc đọc một lượng dữ liệu lớn trong trường hợp cần phải cân nhắc kỹ các các yếu tố như thời gian và cấp phát bộ nhớ để cải thiện hiệu nǎng tổng thể của hệ thống.

Cách tốt nhất để bắt đầu là chúng ta hãy xem xét một thí dụ cụ thể. Giả sử bạn cần đọc dữ liệu lớn từ một tệp nhị phân kích thước lớn và lưu vào một mảng để tiếp tục xử lý. Các thao tác I/O của Java đều dựa trên các stream (dòng), tức một chuỗi tuần tự các byte dữ liệu. Đầu tiên, bạn phải chọn loại stream. Chúng ta làm việc với các tệp nhị phân, vì vậy cần phải sử dụng lớp FileInputStream. Bạn có thể sử dụng lớp FileReader khi làm việc với các stream dữ liệu ký tự. Chúng ta có thể mở một kết nối (connection) tới tệp dữ liệu theo cách sau:

InputStream in = new FileInputStream (fileName);

Tại thời điểm này, bạn đã có thể đọc dữ liệu từ tệp fileName. Tuy nhiên, với ưu tiên về hiệu nǎng, chúng ta hãy xem xét một lớp khác từ gói (package) java.io - BufferedInputStream. Đây là lớp bọc (wrapper) của các stream nhập, nó cho phép lưu vào bộ đệm (buffering) các dữ liệu đầu vào của các stream để cải thiện tiến trình đọc. Bạn có thể kết nối với tệp như dưới đây:

InputStream is = new BufferedInputStream (new FileInputStream (fileName));

Khi đã thiết lập được kết nối tới tệp, bạn cũng có thể bắt đầu đọc nội dung của nó. Lớp InputStream có hai phương thức chính cho việc đọc dữ liệu: int read() và int read (byte[] b, int off, int len). Phương thức thứ nhất chỉ đọc một byte dữ liệu một lần. Trái lại, phương thức thứ hai đọc nhiều byte một lúc (xác định theo tham số len) từ stream vào một mảng. Phương thức thứ hai có hiệu quả cao hơn và chúng ta có thể sử dụng nó trong Listing1.

Listing1

/**
* Đọc tệp và lưu dữ liệu vào mảng.
* Tham số file: tệp dữ liệu cần đọc
*
public byte[] read2array(String file) throws Exception {
InputStream in = null;
byte[] out = new byte[0];
try{
in = new BufferedInputStream(new FileInputStream(file));
// the length of a buffer can vary
int bufLen = 20000*1024;
byte[] buf = new byte[bufLen];
byte[] tmp = null;
int len = 0;
while((len = in.read(buf,0,bufLen)) != -1){
// mở rộng mảng
tmp = new byte[out.length + len];
// copy dữ liệu
System.arraycopy(out,0,tmp,0,out.length);
System.arraycopy(buf,0,tmp,out.length,len);
out = tmp;
tmp = null;
}
}finally{
//đóng stream
if (in != null) try{ in.close();}catch (Exception e){}
}
return out;
}

Có một số khía cạnh rất đáng quan tâm trong thí dụ này. Trước tiên, vì tệp có kích thước lớn, chúng ta cần một bộ nhớ đệm cũng khá lớn (20Mb) khi gọi phương thức đọc. Bộ nhớ đệm càng lớn, đọc dữ liệu sẽ càng nhanh. Trên thực tế, có những trường hợp ta không thể biết trước số byte cần đọc từ một stream nhập nên cần phải cấp phát bộ một dung lượng cố định ban đầu cho bộ nhớ đệm. Điều này có thể giải quyết được bằng cách sử dụng các phương thức thích hợp.

Tuy nhiên, phương thức này không phải lúc nào cũng cho kết quả mong muốn và có thể sinh ra các biệt lệ (exception). Biệt lệ có thể nảy sinh khi đọc các dữ liệu kiểu long hoặc BLOB qua stream. Thứ hai, vì được khởi tạo ở bên ngoài vòng while, các mảng out, buf và tmp có thể được sử dụng lại và hạn chế đối tượng cần phải giải phóng ở thường trình thu nhặt rác. Thứ ba, khi bộ đệm đầy, nó được copy vào một mảng có khả nǎng mở rộng kích thước bằng cách gọi phương thức System.arraycopy. Mặc dù thuật toán này khá hiệu quả nhưng tất cả các vòng lặp read đều tạo ra các mảng tạm thời và cần thực hiện 2 thao tác copy mảng trong một lần lặp.

Bạn có thể giảm thao tác copy dữ liệu và bộ nhớ cho mảng bằng cách thay đổi vòng lặp while như Thí dụ 2 dưới đây.

Listing2

/**
* Đọc tệp và lưu dữ liệu vào một danh sách. Phương pháp nhanh
* Tham số file: tệp dữ liệu cần đọc
*
*/
public byte[] read2list(String file) throws Exception {
InputStream in = null;
byte[] buf = null; // output buffer
int bufLen = 20000*1024;
try{
in = new BufferedInputStream(new FileInputStream(file));
buf = new byte[bufLen];
byte[] tmp = null;
int len = 0;
List data = new ArrayList(24); // lưu "các mảnh" dữ liệu
while((len = in.read(buf,0,bufLen)) != -1){
tmp = new byte[len];
System.arraycopy(buf,0,tmp,0,len); // vẫn cần copy
data.add(tmp);
}
/*

Đoạn này có thể tuỳ chọn. Phương pháp này có thể trả về một List dữ liệuđể xử lý sau này

*/
len = 0;
if (data.size() == 1) return (byte[]) data.get(0);
for (int i=0;i<data.size();i++) len += ((byte[]) data.get(i)).length;
buf = new byte[len]; // bộ đệm xuất cuối cùng
len = 0;
for (int i=0;i<data.size();i++){ // điền dữ liệu
tmp = (byte[]) data.get(i);
System.arraycopy(tmp,0,buf,len,tmp.length);
len += tmp.length;
}
}finally{
if (in != null) try{ in.close();}catch (Exception e){}
}
return buf;

Ơ' đây, thay vì lưu dữ liệu ngay vào một mảng lớn và mở rộng mảng này vào những lúc dữ liệu được thu về, chúng ta duy trì một danh sách với các phần tử là các "mảnh" dữ liệu. Khi đã đến cuối stream, dữ liệu được lấy ra từ danh sách và điền vào một mảng. Điều này cho phép bạn chỉ cần sử dụng tới một mảng và thực hiện một thao tác copy dữ liệu. Nếu không cần kết quả trả về dưới dạng mảng, bạn có thể trả về danh sách để tiết kiệm thời gian và tài nguyên. Đọc dữ liệu sử dụng thuật toán này nhanh hơn đáng để so với phương pháp thứ nhất. Sự khác biệt trong tốc độ phụ thuộc vào kích thước mảng đệm sử dụng trong phương thức đọc


Nguồn
http://www.itgatevn.com.vn

Lập trình mạng, ứng dụng Swing trong bài toán TCP Socket

Swing là một gói giao diện hỗ trợ phát triển các ứng dụng GUI (Graphical User Interface), nó là một phần quan trọng của thư viện Java. Nó được phát triển dựa trên gói giao diện AWT (Abstract Windows Toolkit ). Ví dụ, lớp JButton của gói Swing dựa trên tính năng của lớp AWT Button, nó không những hiện thị nhãn lên Button mà còn hiện thị được cả các ảnh minh họa.


Các thành phần của Swing
Chúng ta sẽ tìm hiểu một số thành phần cơ bản của Swing, như là:

JFrame
JPanel
JButton
Nếu bạn biết cách sử dụng các thành phần cơ bản này, thì các thành phần khác sử dụng cũng tương tự. Thông thường, trong khi tạo các ứng dụng có GUI thì JFrame sẽ được dùng và có dễ dàng chọn cách bố trí các thành phần (layout) lên nó.

Sau đó, nhúng các JPanel trong JFrame nếu muốn. JPanel cũng dễ dàng cài đặt các layout cho phù hợp. Sau đó, thêm các thành phần khác lên các JPanel cho phù hợp. Sau đây là một ví dụ đơn giản:

import java.lang.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class SimpleGui1 {
public static void main(String args[]) {
// Tạo nút có nhãn là “Click Me”
JButton btn = new JButton("Click Me!");
// cho phép người dùng sử dụng phím tăt Alt+C
btn.setMnemonic(KeyEvent.VK_C);
//Cài đặt JPanel theo flowlayout.
JPanel pane = new JPanel(new FlowLayout());
pane.add(btn); //Them nut btn vao JPanel pane
// Tạo JFrame
JFrame fr = new JFrame();
fr.setContentPane(pane);
// Đóng chương trình
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Giao diện xuất hiện ở tọa độ (200, 200)
fr.setLocation(200, 200);
// Hiện thị JFrame fr
fr.setVisible(true);
}
}
Xử lý sự kiện
Bây giờ, ta có thể nhúng phần xử lý sự kiện vào nút “Click Me” , vi dụ, ta cần đưa sự kiện nhấp chuột vào nút “Click Me”, và sau khi sự kiện nhập chuột xảy ra thì ẩn nút đó đi.

Để làm được việc đó, chúng ta cần thực hiện các bước sau:

1. Khai bào thư viện sự kiện java.awt.event.*;

2. Đăng ký sự kiện: nút “Click Me” phải đăng ký sự kiện rằng người dùng nhấp chuột vào đó thì sảy ra sự kiện nhấp chuột.

3. Xử lý sự kiện bằng cách hiện thức giao diện ActionListener và viết chương trình xử lý sự kiện trong hàm “public void actionPerformed(ActionEvent e)”



Tham khảo vị dụ dưới đây:

import java.lang.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class SimpleGui2 {
private static JFrame fr = null;
private static JButton btn = null;

public static void main(String args[]) {
// Tạo nút “Click Me”
btn = new JButton("Click Me!");
//Sử dụng phím tắt Alt+C
btn.setMnemonic(KeyEvent.VK_C);
// nut btn đăng ký sử lý xự kiện

btn.addActionListener(new ButtonListener());

JPanel pane = new JPanel(new FlowLayout());
pane.add(btn);

fr = new JFrame();
fr.setContentPane(pane);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.setLocation(200, 200);
fr.setVisible(true);
}

// Xử lý sự kiện khi người dùng nhấp chuôt vào nút “Click Me”
static class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
btn.setEnabled(false); // Vô hiệu hóa nút
}
}
}
Bây giờ, chúng ta tìm hiểu cách tạo giao diện (sử dụng Swing) cho
bài toán gửi tin nhắn giữa hai máy tình thông qua cơ chế TCP
Lập trình Chat với TCP
Đây là bài toán Chat đơn giản, thông qua ví dụ này các bạn có thể hiểu được cách kết hợp Swing và TCP như thế nào, từ đó, các bạn có thể sáng tạo ra các bài toán phức tạp hơn, nhiều chức năng hơn và có giao diện đẹp hơn.

Khi hai người muốn chát với nhau thông qua chương trình này, mỗi một người sẽ chạy trên một máy riêng biệt. Hoặc chạy chương trình trên cùng một máy thông qua localhost, giống như ví dụ ở bài viết trước. Để sử dụng một cách hiểu qua, chúng ta cần:

Lựa chọn host cho hai máy và phải cùng cổng với nhau.
Giả sử máy chủ chạy trên địa chỉ IP là: huongns, port là 1234, khi đó người dùng máy chủ lựa chọn Host, điền vào ô port là 1234 rồi nhấp chuột vào nút “Connect” và chờ máy khách kết nối đến.
Còn bên máy khách sẽ lựa chọn Guest, điền vào ô port là 1234, điển vào ô Host IP là huongns và nhấp chuột vào nút “Connnect”
Khi hai máy kết nối được với nhau, hai người ngồi ở hai máy có thể chat với nhau bằng cách soạn tin nhắn vào ô chát và enter
Để tăt kết nối, nhấp chuột vào nút “Disconnect”
Để thoát chương trình, nhấp chuột vào ô X ở góc phải-trên màn hình cửa sổ.


Sau đây là chi tiết đoạn mã của bài toán trên: (Tác giả muốn gửi file nguồn nhưng hiện tại forum chưa có chức năng upload file, dó đó bạn đọc nào cần file nguồn có thể liện lạc với tác giả)



import java.lang.*;

import java.util.*;

import java.io.*;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import java.net.*;



public class TCPChat implements Runnable {

// Khởi tạo các trạng thái kết nối

public final static int NULL = 0;

public final static int DISCONNECTED = 1;

public final static int DISCONNECTING = 2;

public final static int BEGIN_CONNECT = 3;

public final static int CONNECTED = 4;



// Khởi tạo một số hằng số

public final static String statusMessages[] = {

" Error! Could not connect!", " Disconnected",

" Disconnecting...", " Connecting...", " Connected"

};

public final static TCPChat tcpObj = new TCPChat();

public final static String END_CHAT_SESSION =

new Character((char)0).toString(); // kết thúc phiên chat



// Thông tin kết nối

public static String hostIP = "localhost";

public static int port = 1234;

public static int connectionStatus = DISCONNECTED;

public static boolean isHost = true;

public static String statusString = statusMessages[connectionStatus];

public static StringBuffer toAppend = new StringBuffer("");

public static StringBuffer toSend = new StringBuffer("");



// Khai báo các thành phần giao diện

public static JFrame mainFrame = null;

public static JTextArea chatText = null;

public static JTextField chatLine = null;

public static JPanel statusBar = null;

public static JLabel statusField = null;

public static JTextField statusColor = null;

public static JTextField ipField = null;

public static JTextField portField = null;

public static JRadioButton hostOption = null;

public static JRadioButton guestOption = null;

public static JButton connectButton = null;

public static JButton disconnectButton = null;



// Khai báo các thành phần TCP

public static ServerSocket hostServer = null;

public static Socket socket = null;

public static BufferedReader in = null;

public static PrintWriter out = null;



/////////////////////////////////////////////////////////////////



private static JPanel initOptionsPane() {

JPanel pane = null;

ActionAdapter buttonListener = null;



// Tạo JPanel

JPanel optionsPane = new JPanel(new GridLayout(4, 1));



// IP

pane = new JPanel(new FlowLayout(FlowLayout.RIGHT));

pane.add(new JLabel("Host IP:"));

ipField = new JTextField(10); ipField.setText(hostIP);

ipField.setEnabled(false);

ipField.addFocusListener(new FocusAdapter() {

public void focusLost(FocusEvent e) {

ipField.selectAll();

// khi ngắt kết nối mới được sửa

if (connectionStatus != DISCONNECTED) {

changeStatusNTS(NULL, true);

}

else {

hostIP = ipField.getText();

}

}

});

pane.add(ipField);

optionsPane.add(pane);



// Cổng

pane = new JPanel(new FlowLayout(FlowLayout.RIGHT));

pane.add(new JLabel("Port:"));

portField = new JTextField(10); portField.setEditable(true);

portField.setText((new Integer(port)).toString());

portField.addFocusListener(new FocusAdapter() {

public void focusLost(FocusEvent e) {

// chỉ được sửa khi đã ngắt kết nối

if (connectionStatus != DISCONNECTED) {

changeStatusNTS(NULL, true);

}

else {

int temp;

try {

temp = Integer.parseInt(portField.getText());

port = temp;

}

catch (NumberFormatException nfe) {

portField.setText((new Integer(port)).toString());

mainFrame.repaint();

}

}

}

});

pane.add(portField);

optionsPane.add(pane);



// lựa chọn host của Guest

buttonListener = new ActionAdapter() {

public void actionPerformed(ActionEvent e) {

if (connectionStatus != DISCONNECTED) {

changeStatusNTS(NULL, true);

}

else {

isHost = e.getActionCommand().equals("host");



// Không thể sửa host nếu đã được chọn

if (isHost) {

ipField.setEnabled(false);

ipField.setText("localhost");

hostIP = "localhost";

}

else {

ipField.setEnabled(true);

}

}

}

};

ButtonGroup bg = new ButtonGroup();

hostOption = new JRadioButton("Host", true);

hostOption.setMnemonic(KeyEvent.VK_H);

hostOption.setActionCommand("host");

hostOption.addActionListener(buttonListener);

guestOption = new JRadioButton("Guest", false);

guestOption.setMnemonic(KeyEvent.VK_G);

guestOption.setActionCommand("guest");

guestOption.addActionListener(buttonListener);

bg.add(hostOption);

bg.add(guestOption);

pane = new JPanel(new GridLayout(1, 2));

pane.add(hostOption);

pane.add(guestOption);

optionsPane.add(pane);



// Nút kết nối và ngắt kết nối

JPanel buttonPane = new JPanel(new GridLayout(1, 2));

buttonListener = new ActionAdapter() {

public void actionPerformed(ActionEvent e) {

// Yêu cầu khởi tạo kết nối

if (e.getActionCommand().equals("connect")) {

changeStatusNTS(BEGIN_CONNECT, true);

}

// Ngăt kết nối

else {

changeStatusNTS(DISCONNECTING, true);

}

}

};

connectButton = new JButton("Connect");

connectButton.setMnemonic(KeyEvent.VK_C);

connectButton.setActionCommand("connect");

connectButton.addActionListener(buttonListener);

connectButton.setEnabled(true);

disconnectButton = new JButton("Disconnect");

disconnectButton.setMnemonic(KeyEvent.VK_D);

disconnectButton.setActionCommand("disconnect");

disconnectButton.addActionListener(buttonListener);

disconnectButton.setEnabled(false);

buttonPane.add(connectButton);

buttonPane.add(disconnectButton);

optionsPane.add(buttonPane);



return optionsPane;

}



/////////////////////////////////////////////////////////////////



// Khởi tạo giao diện

private static void initGUI() {

// Cài đặt trạng thái

statusField = new JLabel();

statusField.setText(statusMessages[DISCONNECTED]);

statusColor = new JTextField(1);

statusColor.setBackground(Color.red);

statusColor.setEditable(false);

statusBar = new JPanel(new BorderLayout());

statusBar.add(statusColor, BorderLayout.WEST);

statusBar.add(statusField, BorderLayout.CENTER);





JPanel optionsPane = initOptionsPane();



// Cài đặt panel chat

JPanel chatPane = new JPanel(new BorderLayout());

chatText = new JTextArea(10, 20);

chatText.setLineWrap(true);

chatText.setEditable(false);

chatText.setForeground(Color.blue);

JScrollPane chatTextPane = new JScrollPane(chatText,

JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,

JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

chatLine = new JTextField();

chatLine.setEnabled(false);

chatLine.addActionListener(new ActionAdapter() {

public void actionPerformed(ActionEvent e) {

String s = chatLine.getText();

if (!s.equals("")) {

appendToChatBox("OUTGOING: " + s + "\n");

chatLine.selectAll();



// Gửi tin chat

sendString(s);

}

}

});

chatPane.add(chatLine, BorderLayout.SOUTH);

chatPane.add(chatTextPane, BorderLayout.CENTER);

chatPane.setPreferredSize(new Dimension(200, 200));



// Cài đặt panel chính

JPanel mainPane = new JPanel(new BorderLayout());

mainPane.add(statusBar, BorderLayout.SOUTH);

mainPane.add(optionsPane, BorderLayout.WEST);

mainPane.add(chatPane, BorderLayout.CENTER);



// Cài đặt Frame chính

mainFrame = new JFrame("Simple TCP Chat");

mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

mainFrame.setContentPane(mainPane);

mainFrame.setSize(mainFrame.getPreferredSize());

mainFrame.setLocation(200, 200);

mainFrame.pack();

mainFrame.setVisible(true);

}



/////////////////////////////////////////////////////////////////





// thay đổi trạng thái

private static void changeStatusTS(int newConnectStatus, boolean noError) {



if (newConnectStatus != NULL) {

connectionStatus = newConnectStatus;

}



// Nếu có lỗi thông báo ở phần trạng thái

if (noError) {

statusString = statusMessages[connectionStatus];

}



else {

statusString = statusMessages[NULL];

}





SwingUtilities.invokeLater(tcpObj);

}



//////////////////////////////////

private static void changeStatusNTS(int newConnectStatus, boolean noError) {



if (newConnectStatus != NULL) {

connectionStatus = newConnectStatus;

}





if (noError) {

statusString = statusMessages[connectionStatus];

}



else {

statusString = statusMessages[NULL];

}







tcpObj.run();

}



/////////////////////////////////////////////////////////////////





private static void appendToChatBox(String s) {

synchronized (toAppend) {

toAppend.append(s);

}

}



/////////////////////////////////////////////////////////////////





private static void sendString(String s) {

synchronized (toSend) {

toSend.append(s + "\n");

}

}



/////////////////////////////////////////////////////////////////





private static void cleanUp() {

try {

if (hostServer != null) {

hostServer.close();

hostServer = null;

}

}

catch (IOException e) { hostServer = null; }



try {

if (socket != null) {

socket.close();

socket = null;

}

}

catch (IOException e) { socket = null; }



try {

if (in != null) {

in.close();

in = null;

}

}

catch (IOException e) { in = null; }



if (out != null) {

out.close();

out = null;

}

}



/////////////////////////////////////////////////////////////////





public void run() {

switch (connectionStatus) {

case DISCONNECTED:

connectButton.setEnabled(true);

disconnectButton.setEnabled(false);

ipField.setEnabled(true);

portField.setEnabled(true);

hostOption.setEnabled(true);

guestOption.setEnabled(true);

chatLine.setText(""); chatLine.setEnabled(false);

statusColor.setBackground(Color.red);

break;



case DISCONNECTING:

connectButton.setEnabled(false);

disconnectButton.setEnabled(false);

ipField.setEnabled(false);

portField.setEnabled(false);

hostOption.setEnabled(false);

guestOption.setEnabled(false);

chatLine.setEnabled(false);

statusColor.setBackground(Color.orange);

break;



case CONNECTED:

connectButton.setEnabled(false);

disconnectButton.setEnabled(true);

ipField.setEnabled(false);

portField.setEnabled(false);

hostOption.setEnabled(false);

guestOption.setEnabled(false);

chatLine.setEnabled(true);

statusColor.setBackground(Color.green);

break;



case BEGIN_CONNECT:

connectButton.setEnabled(false);

disconnectButton.setEnabled(false);

ipField.setEnabled(false);

portField.setEnabled(false);

hostOption.setEnabled(false);

guestOption.setEnabled(false);

chatLine.setEnabled(false);

chatLine.grabFocus();

statusColor.setBackground(Color.orange);

break;

}







ipField.setText(hostIP);

portField.setText((new Integer(port)).toString());

hostOption.setSelected(isHost);

guestOption.setSelected(!isHost);

statusField.setText(statusString);

chatText.append(toAppend.toString());

toAppend.setLength(0);



mainFrame.repaint();

}



/////////////////////////////////////////////////////////////////



// hàm chính

public static void main(String args[]) {

String s;



initGUI();



while (true) {

try { tạm dựng 10/1000 giây

Thread.sleep(10);

}

catch (InterruptedException e) {}



switch (connectionStatus) {

case BEGIN_CONNECT:

try {

// kết nối đến host

if (isHost) {

hostServer = new ServerSocket(port);

socket = hostServer.accept();

}



// kết nối đến server

else {

socket = new Socket(hostIP, port);

}



in = new BufferedReader(new

InputStreamReader(socket.getInputStream()));

out = new PrintWriter(socket.getOutputStream(), true);

changeStatusTS(CONNECTED, true);

}

// Nếu lỗi thì xuất thông báo

catch (IOException e) {

cleanUp();

changeStatusTS(DISCONNECTED, false);

}

break;



case CONNECTED:

try {

// Gửi dữ liệu

if (toSend.length() != 0) {

out.print(toSend); out.flush();

toSend.setLength(0);

changeStatusTS(NULL, true);

}



// Nhận dữ liệu

if (in.ready()) {

s = in.readLine();

if ((s != null) && (s.length() != 0)) {



if (s.equals(END_CHAT_SESSION)) {

changeStatusTS(DISCONNECTING, true);

}



// Nhận tin

else {

appendToChatBox("INCOMING: " + s + "\n");

changeStatusTS(NULL, true);

}

}

}

}

catch (IOException e) {

cleanUp();

changeStatusTS(DISCONNECTED, false);

}

break;



case DISCONNECTING:

//thông báo trạng thái ngắt kết nối

out.print(END_CHAT_SESSION); out.flush();



//xóa

cleanUp();

changeStatusTS(DISCONNECTED, true);

break;



default: break; // thoát

}

}

}

}



////////////////////////////////////////////////////////////////////





class ActionAdapter implements ActionListener {

public void actionPerformed(ActionEvent e) {}

}

Nguồn
http://www.itgatevn.com.vn

RMI & CORBA: Khái niệm và Ứng dụng (Phần 1)

B]MRI & CORBA[/B] là hai khái niệm cơ bản và nền tảng trong kiến thức về Java. Bài viết này sẽ giúp bạn hiểu để ứng dụng hai khái niệm này.


Các đối tượng phân tán

Trong lập trình Java thông thường thì tất cả các đối tượng tạo nên một chương trình sẽ nằm trên cùng một máy và trong cùng một tiến trình hay trên cùng một máy ảo Java (JVM).

Khi một đối tượng gọi một phương thức trên một đối tượng khác thì đối tượng gọi phải biết địa chỉ vùng nhớ của đối tượng bị gọi và có thể chỉ thay đổi bộ đếm chương trình máy để bắt đầu chạy trong một đối tượng mới. Địa chỉ của đối tượng được goik được lưu trữ trong ngăn xếp của máy, vì thế khi phương thức được gọi trả về giá trị thì địa chỉ trong ngăn xếp sẽ được nạp lại vào trong bộ đếm chương trình máy và tiếp tục thực thi trở lại trong đối tượng gọi. Dãy các bước trên là chung đối với tất cả các ngôn ngữ lập trình mà thực thi trong một tiến trình đơn, trên cùng một máy

Triệu gọi phương thức từ xa (RMI) và kiển trúc môi giới yêu cầu đối tượng chung (CORBA) là tầng giữa hỗ trợ việc gọi phương thức phân tán

Nền Java lý tưởng cho việc lập trình phân tán vì nhiều lý do:

· Nền Java định nghĩa một kích thước nhất quán và định dạng cho các kiểu cơ bản, như kiểu số nguyên và số thực, cũng như việc thể hiện các số giống nhau cho tất cả cài đặt trên nền. Đây là phương tiện để cơ chế chuyển tải có thể được đơn giản hóa một cách quan trọng vì nó không phải thực hiện bất kỳ dịch chuyển hay điều chỉnh nào khi nói chuyện với phía bên kia.

· Các hàm thư viện chính dành cho lập trình phân tán trên Java là RMI lại là một phần trong phiên bản chuẩn của ngôn ngữ Java và vì thể nó có trên tất cả các hệ thống hỗ trợ Java

· Java RMI dễ sử dụng

· Các bộ nạp lớp (classloader) của Java có thể tự động tải các đoạn mã bên phía máy khách đối với mô hình nặng về phía máy khách hay các ứng dụng ngang hàng

· Các tham số của Java có thể được truyền tham chiếu hay tham trị

· Nếu bạn không chắc rằng ngôn ngữ Java có trên tất cả các phia của một ứng dụng phân tán, bạn vẫn có thể dùng ngôn ngữ để gọi các đối tượng trên hệ thống khác được viết bằng một ngôn ngữ lập trình khác, ví dụ C++, bằng cách sử dụng CORBA

· Cuối cùng nền Java cũng hỗ trợ cho nhiều kỹ thuật lập trình phân tán khác nhu mô hình lập trình socket
Tại sao chúng ta lại muốn tính toán phân tán?

· Tính toán phân tán được dùng khi có một nguồn tài nguyên trung tâm, ví dụ như một cơ sở dữ liệu mà chúng ta muốn chia sẻ cho nhiều người sử dụng hay nhiều máy khách

· Tính toán phân tán được dùng để kết hợp sức mạnh tính toán của nhiều hệ thống để giải quyết một bài toán hiệu quả và nhanh hơn việc thực hiện với một hệ thống đơn.

Nhiều hệ thống máy tính có thể được cấu hình theo nhiều cách để chia sẻ xử lý, bao gồm chia sẻ bộ nhớ, chia sẽ đĩa, và còn chia sẻ kênh giao tiếp chung. Kỹ thuật gần đây cho phép các hệ thống mà các thành phần vật lý ở xa nhau có thể hợp tác với nhau trong việc giải quyểt các bài toán tính toán

Cũng trên ảnh hưởng của chủ đề sức mạnh tính toán thì sự trỗi dậy của mạng Internet và giao thức TCP/IP đi kèm cũng dẫn đến việc kết nối chưa hề thấy của hàng triệu các hệ thống máy tính. Đối với một vài ứng dụng thì cần sức mạnh tính toán để giải quyết các bài toán.

Chúng ta hãy cùng xem xét 3 mô hình đã từng ảnh hưởng đối với tính toán phân tán:

· Thin client-server: mô hình này đã phổ biến hôm nay, với sự phổ biến của các trình duyệt web. Trong mô hình này thì không có các đoạn mã của ứng dụng chạy trên máy khách – máy khách thực hiện yêu cầu của các phản hồi nhận được từ máy chủ thông qua trình duyệt web; máy chủ sẽ thực thi yêu cầu và gởi về các phản hồi cho máy khách. Đặc tính đẹp nhất của mô hình này là một người dùng có thể thực thi ứng dụng một cách tùy ý mà không cần phải cài đặt, và người dùng có thể chạy ứng dụng từ bất cứ nơi đâu thông qua Internet. Mô hình này ít sử dụng đến các tính toán phân tán, trừ các giao diện người dùng và một vài kiểm tra định dạng và các hàm xử lý đơn giản thông qua các ngôn ngữ như JavaScript. RMI có thể được sử dụng như là một giao thức trong các môi trường này nhưng nói chung thì không nên thay vào đó thì HTTP là giao thức phổ biến hơn trong mô hình này.

· Thick client-server: Mô hình này được dùng khi cần nhiều xử lý bên phía máy khách. Thick client có thể cung cấp một người dùng với một ứng dụng nhiều chức năng. Tuy nhiên phải có một bước cài đặt đẻ lấy mã người dùng cho ứng dụng trên máy người dùng. RMI thì được dùng phổ biến trong mô hình này

· Peer-to-peer: Nếu chúng ta đặt mối quan hệ giữa máy chủ và máy khách ngang nhau, cho phép cả 2 có thể gởi yêu cầu cho nhau khi đó chúng ta có mô hình ngang hàng. Mô hình này đang phát triển và ngày càng phổ biển, nhiều chương trình chia sẻ nhạc MP3 đều sử dụng mô hình này. RMI có thể được dùng như một giao thức trong môi trường này

Có rất nhiều kỹ thuật có sẵn hiện nay cho việc truyền đạt thông tin, như việc thực thi các đoạn mã chương trình từ xa, và phối hợp xử lý giữa các tiến trình trên cùng máy hay các máy đặt xa nhau.

Một trong những kỹ thuật sớm nhất và vẫn còn phổ biến là mở đường liên kết để truyền đạt thông tin giữa các tiến trình. Khi mà liên kết này được thiết lập thì một tiến trình có thể gởi một luồng dữ liệu được mã hóa cho những hành động xác định và thông tin cần truyền đạt đển một tiến trình khác. Tiến trình này sẽ giải mã luông thông tin và thực hiện một hành động, thường là trả kết quả ngược lại cho tiến trình khởi tạo. Lập trình Socket là một ví dụ của kỹ thuật này, một ví dụ khác là giao thức HTTP cho phép chuyển các thông tin HTML mã hóa giữa máy khách và máy chủ

Vấn đề của kỹ thuật này là người lập trình phải suy nghĩ ra một giao thức và sự phối hợp các lệnh cho mỗi ứng dụng. Kỹ thuật này dẫn đến 2 biến hóa khác nhau là gọi một thủ tục, mô hình truyền tham số địa phương tới ngôn ngữ lập trình và mô hình xử lý lệnh cho lập trình socket. Bên cạnh đó cũng có những điểm khác biệt trong định dạng dữ liệu và thứ tự chuẩn của các bit giữa 2 máy, từ đó làm phức tạp mã.

Một mô hình khác là triệu gọi thủ tục từ xa (RPCs). Ở đây, một lập trình viên có thể gọi một thủ tục từ xa và truyền tham số ngược trở lại và về phía trước giống như việc gọi một thủ tục cục bộ. Điều này cho phép phong cách lập trình giống nhau có thể được dùng cho cả lập trình cục bộ và lập trình phân tán. Vẫn còn tồn tại vấn đề định dạng dữ liệu và thứ tự chuẩn của các bit, ngoài ra RPC không tuân theo mô hình hướng đối tượng

RMI là một giải pháp của Java. RMI cho phép các mô hình lập trình giống nhau để gọi các phương thức hướng đối tượng trên cùng máy cục bộ hay gọi phân tán, giả sử rằng ngôn ngữ Java được dùng cho cả bên gọi và bên phương thức được gọi. RMI cho phép các tham số có thể được truyền một trong 2 cách là:

· Truyền theo tham trị: khi một đối tượng mới được tạo ra trong một tiến trình khác và một bản sao của tham số được tạo ra và đưa vào đối tượng mới.
· Truyền theo tham chiếu: một đối tượng không được tạo ra trong tiến trình khác mà được tham chiếu đến từ xa.

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ương thức từ xa và trả về giá trị cho các ứng dụng tính toán phân tán. Chúng ta giả sử rằng 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ận kết quả trả về, nhưng không giống như RMI, nó có thể được sử dụng khi bên phía gọ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ác nhau, bao gồm cả trường hợp là cả 2 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ả 2 bên đều sử dụng cùng môt ngô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ương thức từ xa dễ giải quyết hơn.

· 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.


RMI

1) TỒNG QUAN VỂ RMI

Trong một ứng dụng không phân tán của java, đoạn mã trong một đối tượng có thể gọi phương thức của một đối tượng khác và máy ảo Java phân giải địa chỉ và truyền tham số từ đối tượng gọi đến phương thức được gọi, ngoài ra nó cũng trả về các giá trị cho đối tượng gọi thực thi phương thức

Trong ứng dụng phân tán, mặc dù đoạn mã lập trình phương thức trông có vẻ giống như trong trường hợp ứng dụng không phân tán, nhưng là một cơ chế hoàn toàn khác nhau được dùng để móc những đối tượng này. Khi một đối tượng muốn gọi một phương thức, nó sẽ gọi một đối tượng bè bạn bên phía máy khách, đối tượng này sẽ đại diện cho đối tượng gọi phương thức bên phía máy chủ. Đối tượng này được gọi là stub

Stub sẽ gọi kiến trúc RMI bên phía máy khách và di chuyển dữ liệu qua mạng đến kiến trúc RMI trên máy chủ, đến lược nó sẽ gọi thực thi một đối tượng bè bạn bên phía máy chủ gọi là skeleton.

Đối tượng skeleton sẽ gọi phương thức của đối tượng thật sự bên phía máy chủ. Đến khi trả lại kết quả thì một cơ chế giống hệt như trên sẽ được gọi thực thi nhưng theo thứ tự ngược lại, khi đó kết quả trả về sẽ được truyền cho đối tượng skeleton trên máy chủ, và được đối tượng này truyền theo đường mạng sử dụng kiến trúc RMI, tiếp đến nó sẽ gọi đối tượng stub bên phía máy khách, và trả về giá trị cho đối tượng gọi phương thức

Cái hay của kiến trúc đối tượng phân tán RMI là người lập trình chỉ cần lập trình các lời gọi phương thức vì đối tượng được gọi đã hiện diện trong máy ảo Java của nó

2) Stub và skeletons

Stub và skeleton được phát sinh ra từ đối tượng gọi và đối tượng được gọi bằng cách sử dụng một công cụ biên dịch của RMI là rmic. Các trình đóng gói ứng dụng phải đảm bảo là các stubs phải được đóng gói kèm theo với các đoạn mã bên phía máy khách hay các tập tin JAR, và các skeleton phải đi kèm với các đoạn mã bên phía máy chủ hoặc các thư viện JAR

Các Stub có thể được tự động tải về từ máy chủ web khi có yêu cầu. Hình dưới đây minh họa luồng dữ liệu giữa stub và skeleton trong kiến trúc của RMI



3) Xây dựng các đối tượng

Hầu như không có khác biệt giữa lập trình trên máy cục bộ và lập trình phân tán trong RMI. Lập trình phân tán chỉ yêu cầu một ít yêu cầu lập trình

Tất cả các lớp muốn có thể được triệu gọi từ xa thì phải có 2 phần: phần giao diện (interface) và phần cài đặt (implementation). Phần giao diện phải thừa kế từ một lớp của Java là lớp Remote. Phần cài đặt không những cài đặt phần giao diện mà còn phải thừa kế từ một lớp của Java là lớp UnicastRemoteObject

Thật sự có một mạng liên lạc tồn tại dưới cơ chế gọi phương thức từ xa, và mạng này có thể có lỗi hay bị ngắt kết nối hoàn toàn. Hoặc máy chủ có thể bị lỗi. Vì vậy bên máy khách có thể có vài lỗi mà nó phải xử lý trong lập trình phân tán. Những lỗi này xuất hiện dưới với dạng ngoại lệ RemoteException, vì thế tất cả phương thức trên đối tượng của máy chủ được thiết kế để được triệu gọi từ xa phải khai báo là nó sẽ tung ra ngoại lệ RemoteException. Mã bên phía máy người dùng nên xử lý những lỗi này khi nó xuất hiện

Dưới đây là một giao diện đơn giản cho một lớp truyền vào và lấy ra một String:

// Example.java
//
// Giao diện cho đối tượng triệu gọi từ xa
//
import java.rmi.*;
public interface Example extends Remote {
public void setString( String s ) throws RemoteException;
public String getString() throws RemoteException;
}


Và đây là phần cài đặt:

// ExampleServer.java
//
// Phần cài đặt đối tượng từ xa cho giao diện Example
//
import java.rmi.*;
import java.rmi.server.*;

public class ExampleServer extends UnicastRemoteObject implements Example {
private String stringState;
public ExampleServer() throws RemoteException{}
public void setString( String s ) throws RemoteException{
stringState = s;
}

public String getString() throws RemoteException{
return stringState;
}
}

Phần tiếp theo chúng ta sẽ tạo stub và skeleton cho lớp ExampleServer bằng cách sử dụng lệnh
rmic ExampleServer

4) RMI Registry

Chúng ta phải xác định được vị trí của đối tượng từ xa, RMI cung cấp một máy chủ chuyên quản lý tên là RMI Registry để thực hiện chức năng này

Một đối tượng có một tên (trong ví dụ này nó có tên là “Example”) và một vị trí của máy (trong ví dụ là “localhost”). Trong đoạn mã sau, chúng ta sẽ tạo một đối tượng ExampleServer và tạo một lối vào RMI Registry đặt trên máy cục bộ và đặt cho nó một cái tên là Example

Chúng ta sử dụng phương thức rebind() để tránh lỗi trong trường hợp tên này đã tồn tại trong RMI Registry, ngược lại chúng ta cũng có thể sử dụng phương thức bind(). Chúng ta chỉ cần chạy đoạn mã này một lần đến khi nào tiến trình của RMI Registry còn hoạt động. Thông tin trong registry không được lưu trữ xuống vĩnh viễn(persistent).

// Server.java
//
// Chương trình trên máy chủ tạo một đối tượng từ xa "Example" và đưa nó vào
// RMI registry
//
import java.io.*;
import java.rmi.*;
import java.rmi.server.*;
public class Server {
public static void main ( String[] args ) throws RemoteException, java.net.MalformedURLException {
//
// Create a new example object and enter it into the RMI registry
// located on "localhost" under the alias "Example"
ExampleServer es = new ExampleServer();
Naming.rebind( "rmi://localhost/Example", es );
}
}

5) Xây dựng chương trình bên phía máy khách

Cuối cùng chúng ta xây dựng một chương trình bên phía máy khách để thực hiện lời gọi từ xa. Đầu tiên, chúng ta phải xác định được vị trí của đối tượng bên phía máy chủ, vì vậy chúng ta phải tìm đối tượng Example trong RMI Registry và gọi một phương thức để truyền vào một chuỗi và đọc ngược nó ra và cuối cùng là xuất nó ra màn hình

// ExampleClient.java
//
// Chương trình bên phía máy khác gọi đối tượng từ xa Example để truyền vào một //.
// chuỗi và đọc nó ra
import java.rmi.*;
public class ExampleClient {
public static void main ( String[] args ) {
try {
// Tìm đối tượng từ xa "Example" trong RMI registry
Example example = (Example) Naming.lookup( "Example" );
//
// Truyền vào một chuỗi và đọc nó ra trở lại rồi xuất ra màn hình
example.setString( "Success!" );
System.out.println( example.getString() );
} catch (Exception e) {
e.printStackTrace();
}
}
}


Để chạy ví dụ chúng ta phải khởi động RMI Registry lên, chạy chương trình bên phía máy chủ một lần, sau đó chúng ta có thể chạy chương trình bên phía người dùng

start rmiregistry
start java Server
java ExampleClient

Nếu thực hiện thành công bạn sẽ thấy kết quả là “Success” trên màn hình

6) Triển khai RMI trên 2 máy khác nhau

Chúng ta sẽ xem xét ứng dụng RMI được viết và chạy một chương trình trong một tiến trình, cùng một JVM và nó liên lạc với một tiến trình khác chạy trên cùng máy. Khi chúng ta tách rời chức năng của hai máy ra, chúng ta sẽ xem xét việc triển khai như thế nào

Nếu chúng ta muốn chạy ví dụ trên 2 máy khác nhau thì

Bên phía máy khách cần có các lớp sau: Example.class, ExampleClient.class, ExampleServer_Stub.class
Bên phía máy chủ cần có các lớp sau: ExampleServer.class, Server.class, Example.class, ExampleServer_Stub.class, ExampleServer_Skel.class

Để có thể linh động hơn, chúng ta có thể đặt tập tin ExampleServer_Stub.class trên một máy chủ Web để tập tin này có thể được tải xuống khi có yêu cầu nếu bạn sử dụng tùy chọn -Djava.rmi.server.codebase khi thực hiện bằng dòng lệnh để chạy chương trình bên phía máy khách. Ví dụ:

java -Djava.rmi.server.codebase=http://www.mywebserver.com/ ExampleClient
Và dưới đây là sơ đồ để triển khai một ứng dụng RMI tiêu biểu

Tham khảo
http://www.itgatevn.com.vn
http://www.sun.com
http://www.ibm.com


RMI & CORBA: Khái niệm và Ứng dụng (Phần 2)

MRI & CORBA là hai khái niệm cơ bản và nền tảng trong kiến thức về Java. Bài viết này sẽ giúp bạn hiểu để ứng dụng hai khái niệm này.


RMI & CORBA: Khái niệm và Ứng dụng (Phần 1)

CORBA

7) Tổng quan vể CORBA

Như đã đề cập ở trước thì CORBA định nghĩa nhiều dịch vụ, một trong những dịch vụ đó thực hiện chức năng tương tự như RMI, nhưng CORBA họat động với nhiều ngôn ngữ lập trình khác nhau và không chỉ với nền Java

CORBA được định nghĩa bởi một liên kết bao gồm 800 công ty thành viên, được gọi là Nhóm Quản Lý Đối Tượng (Object Management Group - OMG)
Nói chung thì CORBA định nghĩa 2 thứ:

Thực thể mà cho phép liên lạc giữa 2 tiến trình được gọi là 1 môi giới yêu cầu đối tượng (Object Request Broker - ORB)

Một giao thức được ORB dùng để liên lạc giữa nhiều tiến trình, được gọi là IIOP (Internet Interoperability Protocol)

Nền của Java chứa 1 CORBA ORB. CORBA dùng cùng kỹ thuật stub/skeleton như RMI, nhưng không giống như RMI, CORBA phát sinh stub và skeleton từ một mô tả giao diện độc lập với ngôn ngữ được gọi là Ngôn Ngữ Mô Tả Giao Diện (Interface Description Language – IDL) thay vì mã nguồn của ngôn ngữ
IDL xác định tên phương thức, cũng như tham số gọi và trả về theo một kiểu ngôn ngữ trung lập

8) Tổng quan về Java IDL và RMI-IIOP

Java IDL và RMI-IIOP cung cấp 2 cách sử dụng đoạn mã Java bên phía máy khách với một đối tượng CORBA trên máy chủ

Với Java IDL thì các bước phát triển bắt đầu bằng định nghĩa giao diện từ xa bằng IDL, sau đó sẽ biên dịch IDL ra một ngôn ngữ đích bên phía máy chủ, tiếp đến là viếts đối tượng từ xa trên máy chủ sử dụng ngôn ngữ đó và triển khai từng phần

Vì không có RMI Registry trong môi trường của CORBA nên Dich Vụ Tên CORBA(CORBA Naming Service – COSNaming) cung cấp chức năng tìm kiếm vị trí đối tượng bên phía máy chủ

Với RMI-IIOP, stub và skeleton được phát sinh ngay từ định nghĩa đối tượng Java. Thay vì sử dụng giao thức trong RMI để liên lạc giữa 2 tiến trình, RMI-IIOP sử dụng giao thức CORBA IIOP để nó có thể gọi các đối tượng không được viết bằng ngôn ngữ Java. Các bước phát triển bắt đầu với cài đặt một lớp phát sinh bằng IDL trong ngôn ngữ Java. Lớp này được biên dịch với rmic dùng cớ hiệu –iiop –d và một lớp bên phía máy chủ sử dụng COSNaming, truy cập Giao Diện Thư Mục và Tên Trong Java (Java Naming and Directory Interface – JNDI)

9) Viết IDL

Chúng ta sẽ xem xét một ví dụ sử dụng CORBA. Đầu tiên chúng ta định nghĩa IDL cho đối tượng từ xa:

interface ExampleCORBA {
attribute string s;
};
Bây giờ chúng ta có thể biên dịch IDL dùng lệnh idlj. Tham số -fall phát sinh mã cả 2 phía máy khách và máy chủ
idlj -fall ExampleCORBA.idl

Sau khi biên dịch IDL, sẽ phát sinh một số tập tin sau:

_ExampleCORBAStub.java là mã stub.
ExampleCORBA.java là giao diện từ xa..
ExampleCORBAHolder.java là mã hỗ trợ.
ExampleCORBAHelper.java là mã hỗ trợ.
ExampleCORBAOperations.java là mã hỗ trợ.
ExampleCORBAPOA.java là mã skeleton và là lớp cha chúng ta thừa kế khi cài đặt mã bến phía máy chủ.

10) Viết đối tượng gọi từ xa

Tiếp đến chúng ta sẽ cài đặt lớp bên phía máy chủ được gọi là Servant và thừa kế từ lớp gốc phát sinh khi dịch IDL:

// ExampleCORBAServant.java
//
// The remote implementation for ExampleCORBAPOA
//
import org.omg.CORBA.*;

public class ExampleCORBAServant extends ExampleCORBAPOA {
private String stringState;
private ORB orb;

public void setORB( ORB o ) {
orb = o;
}

public String s() {
return stringState;
}

public void s( String s ) {
stringState = s;
}
}

11) Chương trình bên phía máy chủ

Tiếp đến chúng ta cài đặt mã bên phía máy chủ, để thực hiện việc khởi tạo đối tượng và đăng ký máy chủ tên:
// CORBAServer.java
//
// Server to make a new "Example" remote object and put a reference to
// it in the name service
//
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import org.omg.PortableServer.*;
import org.omg.PortableServer.POA;

public class CORBAServer {

public static void main ( String[] args ) {
try {
//
// Initialize the ORB
ORB orb = ORB.init( args, null );
POA rootpoa =
POAHelper.narrow( orb.resolve_initial_references("RootPOA"));
rootpoa.the_POAManager().activate();
//
// Create a new remote Example object, set the ORB in it
// enter it into the name server
ExampleCORBAServant e = new ExampleCORBAServant();
e.setORB(orb);
//
// Make a reference to the object
org.omg.CORBA.Object ref = rootpoa.servant_to_reference(e);
ExampleCORBA eRef = ExampleCORBAHelper.narrow(ref);
//
// Find the name service
org.omg.CORBA.Object oRef =
orb.resolve_initial_references("NameService");
NamingContextExt ncRef = NamingContextExtHelper.narrow( oRef );
//
// Enter the reference into the name service
String name = "Example";
NameComponent path[] = ncRef.to_name( name );
ncRef.rebind(path, eRef);
//
// Wait and listen for requests
orb.run();

} catch (Exception e) { e.printStackTrace(); }
}
}

12) Chương trình bên phía máy khách

Cuối cùng chúng ta tạo ra một chương trình bên phía máy khách để thực hiện lới gọi phương thức từ xa:
// ExampleCORBAClient.java
//
// CORBA client for calling remote "Example" object
//
import org.omg.CosNaming.*;
import org.omg.CORBA.*;

public class ExampleCORBAClient {

public static void main ( String[] args ) {
try {
//
// Initialize the ORB
ORB orb = ORB.init( args, null );
//
// Find the nameserver and downcast it from
// Object to NamingContext
org.omg.CORBA.Object o =
orb.resolve_initial_references( "NameService" );
NamingContext ns = NamingContextHelper.narrow(o);
//
// Find the "Example" alias in the root path and downcast it to
// ExampleCORBA
NameComponent nc = new NameComponent( "Example", "");
NameComponent path[] = {nc};
o = ns.resolve( path );
ExampleCORBA example = ExampleCORBAHelper.narrow( o );
//
// Call the Example remote object to set the string and read and
// print it
example.s( "CORBA Success!" );
System.out.println( example.s() );

} catch (Exception e) { e.printStackTrace(); }
}
}


13) Chạy ứng dụng CORBA

Để thực thi đoạn mã ví dụ, chúng ta phải khởi động RMI Registry, chạy đoạn mã bên phía máy chủ một lần, sau đó chúng ta có thể chạy chương trình khách:

start tnameserv
start java CORBAServer
java ExampleCORBAClient -ORBInitialHost localhost
Kết quả xuất ra màn hình là “CORBA Success!”
TỔNG KẾT
Bạn đã trông thấy cả RMI và CORBA thực hiện cùng một chức năng là chương trình bên phía máy khách gọi phương thức của một đối tượng nằm bên phía máy chủ. Tuy nhiên làm thế nào để biết khi nào chọn RMI hay CORBA. Nếu bạn sử dụng nền Java ở cả 2 môi trường đầu cuối trong ứng dụng phân tán thì nên chọn RMI vì lập trình và mô hình triển khai đơn giản. Nếu bạn cần có một chương trình Java nói chuyện với một đối tượng không được viết bằng ngôn ngữ Java và nằm trên máy chủ, khi đó bạn nên chọn CORBA

Tham khảo
http://www.itgatevn.com.vn
http://www.sun.com
http://www.ibm.com

New Blog

Lần đầu tiên làm Blog Opera lên không có nhìu kinh nghiệm mong được sự ủng hộ của mọi người!!!1
Thanks!!!! nhìu!!!!!!!!!!^_^