Mô hình tính toán CLIENT/SERVER

Khi nói tới lập trình mạng ta thường nghĩ đến cách trao đổi giữa một chương trình phục vụ (Server) với một hay nhiều chương trình khách (Client) [2], Chương trình khách gửi một yêu cầu tới cho chương trình phục vụ, và chương trình này xừ lý dừ liệu để trả lời cho chương trình khách. Như vậy, chương trình khách muốn gửi được yêu cầu thi trước hết phải tim cách kết nối VỚI Server. Server có thể chấp nhận hay từ chối sự kết nối này. Một khi sự kết nối đã được thiết lập thỉ Client và Server trao đồi với nhau thông qua Sockets. Các lóp trong gói java.net cung cấp các phương thức để kết nối mạng và trao dổi tin giữa các máy với nhau theo mô hình Client/server. Mặt khác, trên Internet nhiều máy tính sứ dụng các giao thức chuẩn để trao đổi với nhau.

Socket chính là lớp (trim tượng) thực hiện sự trao đổi giữa Server và Client. Java xem sự trao đổi giữa Server và Client dựa trên Socket gần giống như các thao tác vào/ra (I/O), nghĩa là các chương trình có thể đọc, ghi vào Socket dễ dàng như chúng đọc, ghi lên tệp dữ liệu. Lớp Server tạo ra sụ kết nối từ máy Client tới Server thông qua các phương thức tạo lập dối tượng.

Lóp ServerSocket dùng để tạo kết nối từ Server tới các máy Client. Đối tượng của lớp này được tạo ra trên Server và lắng nghe những kết nối từ mảy Client theo cổng xác đinh. Server phải chạy thướng trục trước khi Client bắt dầu thực hiện. Server chờ sự yêu cầu kết nối của Client. Các Socket được xác định tương ứng với địa chỉ của máy và cồng. Để thiết lập được một Server, ta phải tạo ra một đối tượng, ví dụ
serverSocket của lóp Server Socket, gắn nó với một cổng nào đó và lắng nghe xem có Client nào cần kết nối hay không.

ServerSocket serverSocket = new ServerSocket(port);

Trong đó, port là số hiệu của cổng nằm giữa 0 và 1023. cồng cho phép trao đổi tin giữa hai chương trinh. Địa chỉ của cổng là số 16 bít và thường phụ thuộc vào các giao thức ứng đụng. Thông thường, giao thức FTP sừ đụng cổng 21, telnet dùng cồng 23, các dịch vụ E-mail (SMTP) sử dụng cổng 25, Web Server chạy trên cồng 80.

Sau khi đối tượng server Socket được tạo ra, Server có thể sừ đụng câu lệnh sau để lẳng nghe yêu cầu kết nối cùa Client.

Socket connectToServer = new Socket(ServerName,port);

serverName là tên của máy chù trên Intermet hoặc địa chỉ ĨP, xác định duy nhất một máy tính trên toàn mạng Internet (cả thế giới). IP là giao thức được sử dụng để gửi tin từ một máy tới mảy khác trên mạng Internet. IP phải xác định được máy gửi và mảy nhận thông qua địa chi IP. Một địa chì IP gồm bốn số nguyên nằm giữa 0 và 255, phân cách với nhau bằng dấu V. Ví dụ

Socket connectToServer = new Socket(“129.74.250.103”, 8000);


Vì địa chỉ IP thường rất khó nhớ nên thay vì địa chỉ IP người ta thường sừ dụng tên miền dịch vụ, ví dụ Gophe.nd.edu tương ứng với địa chi IPnêu trên.

Ngày nay, trên Internet hai máy có thể trao đổi với nhau phần lớn đều dựa trên giao thức chuẩn TCP/IP.

Sau khi sự kểt nối đã được Server chấp nhận, việc trao đổi giữa Client và Server giống như trên các luồng vào/ra I/O.

Ví dụ

Inputstream isl’r omServer = connectToServer. getlnputStreamO ; Outputstream osToServer = connectToServer. getoutputstream!);

Tạo ra luồng vào/ra: isFrcmServer để đọc từ Server và osToServer để ghi vào (gửi cho) Server. Hai lớp Irputstream, CXitputStream được sừ dụng để đọc và ghi từng byte Ta cũng có thể sử dụng DataOutputStream, Datalnputputstream, Buf feredReader, PrintWriter để đọc, ghi dữ liệu kiểu int, double, string, v.v. Ví dụ, đoạn chưomg trình sau tạo ra isFrcrrClient, osToClient để đọc, ghi các dừ liệu kiểu nguyên thủy ờ Client

DataInputstream isFromClient = new DataInputstream

(connectToClient.getInputStream());

DataOutputStream osFromClient = new DataOutputStream

(connectToClient.getOutputStream());

Server có thể sử dụng isFromCl lent. read 0 để nhận dữ liệu từ Client và isFromClient. write () để gừi dữ liệu cho Client

Ví dụ 3.3. Chúng ta hãy xét một chương trình Client gửi dữ liệu là bán kính của đường tròn cho Server . Server nhận dừ liệu này, tính diện tích của hình tròn và sau đó gửi kết quả lại cho chương trình khách.

// Server.java nhận dữ liệu từ Client, tính diện tích hình tròn và gửi lại kết quả cho Client import java.io.*; import j ava.net.*; public class Server! public static void mainfstring arg[]){ try!

// Tạo ra socket server

ServerSocket serverSocket = new ServerSocket(8000);

// Lang nghe yêu cầu kết nối trên socket server

Socket connectToClìent = serverSocket.accept{);

// Tạo ra một luồng vào để nhận dữ liệu từ Client

Datalnputstream isFromClient = new Datalnputstream ( connectToClient.getlnputstream());

// Tạo ra một luồng ra để gửi dữ liệu cho Client

DataOutputStream osToClient = new DataOutputStream( connectToClíent.getoutputstream());

// Liên tục nhận, xử lý và gửi kết quả lại cho Client while(true){

// Đọc một số double từ Client

double radius = isFromClient.readDouble( ) ; SystQTi.out.println(“Ban kinh nhan tu Client: ” + radius); double area = radius * radius * Hath.PI ;

// Gửi kết quả: diện tích kiểu double cho Client osToClient.writeDouble(area); osToClient.flush();

Systan.out.println(‘,ttinh tran CD ben kinh: ” + radius + ” CD dion tích: ” + area) ;

}

}catch(IOException ex){

System.err.printIn(ex);

}

}

}

// Client.java nhập dữ liệu (bán kính) tù bàn phím, gửi cho Server, nhận và hiển thị // diện tích hình ưòn nhận được .

import j ava.io.* ; import java.net.* ; public class Client[ public static void main(String arg[]){ try {

// Tạo ra một socket để kết nối với socket server

Socket connectToServer = new Socket(“localhost”, 8000);

// Tạo ra một luồng vào để nhận dữ liệu từ server

Datalnputstream isFromServer = new Datalnputstream( connectToServer.getlnputstream{));

// Tạo ra một luồng ra để gùi dữ liệu đến server

DataOutputStream osToServer = new DataOutputStream ( connectToServer.getoutputstream ( )) ;

// Tạo ra một luồng vào để nhập dừ liệu từ bàn phím Datalnputstream. str = new Datalnputstream(System.in);

// Liên tục gửi dữ liệu nhập vào từ bàn phím cho server và nhận lại diện tích while(true){

// Nhập bán kính từ bàn phím

System.out.print(“Hay cho bìet ban kinh: “); double radius = Double.parseDouble(str.readLine0);

// Gửi dữ liệu cho server

osToServer.writeDouble(radius);

osToServer.flush();

// Nhận lại kết quả tù server

double area = isFromServer.readDouble ( );

System, out .printin (“Dien tichhinh tron nhan duoc tu Servo-: “+ area);

}

}catch (IOException ex) {

System.err.println(ex);

}

}

}

Hai chương trình trên thực hiện liên tục, chương trình Client chờ nhập bán kính của hình tròn và trao đổi với Server cho đến khi một trong hai chương trình kết thúc (nhấn CTRL+C) hay nhấn biểu tượng kết thúc chương trình.