Các phương pháp truyền thông ClientServer Khái niệm Các phương pháp truyền thông (Khái quát): Chương trình mô phỏng chat đơn giản thông qua socket Chương trình mô phỏng hàng đợi đa mức có phản hồi Bài toán người đọc và biên tập viên Bài toán người thợ cắt tóc ngủ gật Bathroom problem Producer Consumer Dining philosophers Bài toán tạo phân tử H2O Đọc Master Boot Record, đưa ra các phân vùng chính của ổ cứng, nếu phân vùng ổ C sử dụng hệ thống file FAT32 thì đưa ra thông tin về ổ.
Trang 1TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
Viện Công nghệ Thông tin và Truyền thông
Trang 2Mục lục
Mục lục 2
1 Khái niệm 2
2 Các phương pháp truyền thông (Khái quát): 3
A Các phương pháp truyền thông Client-Server
1 Khái niệm
Mô hình client-server là một mô hình nổi tiếng trong mạng máy tính, được áp dụngrất rộng rãi và là mô hình của mọi trang web hiện có Ý tưởng của mô hình này là máy con (đóng vài trò là máy khách) gửi một yêu cầu (request) để máy chủ (đóng vai trò người cung ứng dịch vụ), máy chủ sẽ xử lý và trả kết quả về cho máy
khách
Trang 3Thuật ngữ server được dùng cho những chương trình thi hành như một dịch vụ trêntoàn mạng Các chương trình server này chấp nhận tất cả các yêu cầu hợp lệ đến từmọi nơi trên mạng, sau đó nó thi hành dịch vụ và trả kết quả về máy yêu cầu Một chương trình được coi là client khi nó gửi các yêu cầu tới máy có chương trìnhserver và chờ đợi câu trả lời từ server
Chương trình server và client nói chuyện với nhau bằng các thông điệp (messages) thông qua một cổng truyền thông liên tác IPC (Interprocess Communication) Để một chương trình server và một chương trình client có thể giao tiếp được với nhau thì giữa chúng phải có một chuẩn để nói chuyện, chuẩn này được gọi là giao thức Nếu một chương trình client nào đó muốn yêu cầu lấy thông tin từ server thì nó phải tuân theo giao thức mà server đó đưa ra
2 Các phương pháp truyền thông (Khái quát):
2.1 Socket
Một socket là một thiết bị truyền thông 2 chiều tương tự như một tập tin
Chúng ta có thể đọc hay ghi lên nó Tuy nhiên mỗi socket là một thành phầntrong một mối nối nào đó giữa các máy trên mạng máy tính và các thao tác đọc/ghi chính là sự trao đổi dữ liệu giữa các ứng dụng trên nhiều máy khác nhau
Ở đây ta hiểu Socket trong Winsock như là một “phương tiện” để ứng dụng
mạng có thể trao đổi dữ liệu Nghĩa là 1 Server thì sẽ cần một Socket để lắngnghe, chờ đợi các kết nối từ client và Client thì phải cần có một Socket đểkết nối tới Sever
2.2 RMI
RMI (Remote Method Invocation) là một cơ chế cho phép một đối tượng
đang chạy trên một máy ảo Java này ( Java Virtual Machine) gọi các phươngthức của một đối tượng đang tồn tại trên một máy ảo Java khác (JVM) Thực chất RMI là một cơ chế gọi phương thức từ xa đã được thực hiện vàtích hợp trong ngôn ngữ Java Vì Java là một ngôn ngữ lập trình hướng đốitượng, nên phương pháp lập trình trong RMI là phương pháp hướng đốitượng do đó các thao tác hay các lời gọi phương thức đều liên quan đến đốitượng Ngoài ra, RMI còn cho phép một Client có thể gửi tới một đối tượngđến cho Server xử lý, và đối tượng này cũng có thể được xem là tham số cho
Trang 4lời gọi hàm từ xa, đối tượng này cũng có những dữ liệu bên trong và cáchành vi như một đối tượng thực sự.
2.3 RPC
RPC (Remote Procedure Calls) – Thủ tục gọi hàm từ xa là một kỹ thuật tiến
bộ cho quá trình kết nối từ Client đến Server để sử dụng các ứng dụng vàdịch vụ RPC cho phép client có thể kết nối tới 1 dịch vụ sử dụng dynamicport nằm ở một máy tính khác Trong hệ thống mạng máy tính hiện nay có rấtnhiều dịch vụ và ứng dụng sử dụng cơ chế kết nối RPC
RPC được thiết kế để cung cấp cho việc truyền tải thông tin giữa client vàserver dễ dànghơn, bảo mật hơn, và thuận tiện hơn cho việc đồng bộ hóa cácluồn dữ liệu
Các thông điệp gửi cho một dịch vụ RPC được biểu diễn bởi ngôn ngữ XDR(External Data Representation): dạng thức biểu diễn dữ liệu ngoài Chỉ có cáckiểu dữ liệu có thể được định nghĩa bởi XDR mới có thể truyền đi
B Chương trình mô phỏng chat đơn giản thông qua socket
public class Server {public static void main(String[] args) {
// Xử lí các trường hợp ngoại lệ có thể xảy ra của các lệnh đặt trong khối try catch
try {
// Khởi tạo sever tại cổng 6132
ServerSocket server = new ServerSocket(1234);
// Tạo vòng lặp vô hạn
while (true) {
System.out.println("Listening ");
// Chờ cho đến khi có Client kết nối tới thì sẽ trả Client về Socket sock
Socket sock = server.accept();
// Lấy thông tin về Client vừa conect tới
InetAddress addr = sock.getInetAddress();
System.out.println("Connection made to " + addr.getHostName()+ " (" + addr.getHostAddress() + ") \n");
Trang 5ObjectInputStream ois = new ObjectInputStream(sock.getInputStream()); ObjectOutputStream oos = new
ObjectOutputStream(sock.getOutputStream());
Object infor = ois.readObject();
System.out.println(infor.toString());
oos.writeObject("Hi, I'm Server \n");
// Đóng kết nối
sock.close();
}
}
catch (ClassNotFoundException x) {System.out.println(x);}
catch (IOException x) {System.out.println("Exception detected: " + x);}
String hostname = "127.0.0.1"; // Địa chỉ để chat trên cùng một máy
// Xử lí các trường hợp ngoại lệ có thể xảy ra của các lệnh đặt trong khối try catch
try {
sock = new Socket(hostname, port);
System.out.println("Connect successfully \n");
ObjectOutputStream oos = new ObjectOutputStream(sock.getOutputStream()); ObjectInputStream ois = new ObjectInputStream(sock.getInputStream()); oos.writeObject("Hello, I'm Client \n");
Object infor = ois.readObject();
System.out.println(infor.toString());
}
catch (ClassNotFoundException x) {System.out.println(x);}
catch (IOException x) {System.out.println(x);}
catch (Exception x) {System.out.println(x);}
}}}}
C Chương trình mô phỏng hàng đợi đa mức có phản hồi
Trang 6* Nhập số lượng tiến trình tham gia điều phối.
* Với mỗi tiến trình thì nhập thời điểm bắt đầu vào hệ thống và thời gian chạy cần thiết để tiến trình hoàn tất.
* Chương trình sẽ in ra thời điểm chạy của các tiến trình.
+ Chương trình:
#include<iostream.h>
#include<stdlib.h>
#define max 100
Trang 7float t[max], b[max];
int q1[max], q2[max], q3[max], vt[max], kt[max], n, f1, r1, f2, r2, f3, r3;
void sort()
{ int i,j,t3; float t1,t2;
for (i=1; i<n; ++i)
void push(int q[], int i, int &f, int &r)
{ if ((max-f+r)%max==max-1) {cout<<"hang doi day"; return;} q[r]=i;
Trang 8cout<<"So luong tien trinh tham gia: "; cin>>n;
for (i=0; i<n; ++i) {
cout<<"Thoi diem tien trinh "<<i<<" xuat hien: "; cin>>b[i]; cout<<"Thoi gian de tien trinh hoan thanh: "; cin>>t[i];
Trang 118 ->12 Tiến trình 1 chạy và kết thúc
12 ->20 Tiến trình 0 đang chạy
20 ->36 Tiến trình 2 đang chạy
• Chỉ cho phép một tiến trình Writers cập nhật CSDL tại một thời điểm
• Vấn đề không trưng dụng Các tiến trình ở trong đoạn găng mà không bịngắt
+ Cài đặt
• Khởi tạo semaphore
Mutex=1; // Kiểm tra truy xuất reader
db=1; // Kiểm tra truy xuất cơ sở dữ liệu
turnstile=1; // Dùng để điều độ tránh tình trạng đói CPU của các tiến trìnhWriters;
• int rc=0; // Số tiến trình Readers truy cập CSDL
Trang 12{Chuẩn bị dữ liệu để ghi}
// Giành quyền truy xuất cơ sở dữ liệu
Trang 13++rc;
if (rc==1) WaitForSingleObject(db,INFINITE);ReleaseSemaphore(mutex,1,NULL);
Trang 14turnstile = CreateSemaphore(NULL,1, 1, NULL);
mutex1 = CreateSemaphore(NULL,1, 1, NULL);
for (i=0; i<3; ++i)
WaitForMultipleObjects(3, h1, TRUE, INFINITE);
WaitForMultipleObjects(10, h2, TRUE, INFINITE);
getch();
return 0;
}
+ 1 đoạn kết quả ví dụ khi chạy chương trình:
Day la lan cap nhat cua writer 0 Day la lan cap nhat cua writer 1 Day la lan capnhat cua writer 0 Day la lan cap nhat cua writer 0 Day la lan cap nhat cua writer 2Day la lan cap nhat cua writer 1 Day la lan cap nhat cua writer 0 Day la lan capnhat cua writer 0 Day la lan cap nhat cua writer 0 Day la lan cap nhat cua writer 0
Trang 15* Như vậy ta thấy các tiến trình đã được điều một cách hợp lí Các câu in ra đầy đủ(chứng tỏ không có sự truy cập file của reader khi writer đang cập nhật), một câu
có thể in ra nhiều lần liên tiếp( chứng tỏ nhiều tiến trình reader có thể truy cập filecùng lúc)
E Bài toán người thợ cắt tóc ngủ gật
+ Nếu thợ cắt tóc đang ngủ thì đánh thức anh ta dậy
+ Nếu thợ cắt tóc đang làm việc:
Nếu không còn ghế đợi trống thì bỏ đi
Nếu còn ghế bỏ trống thì ngồi đợi
Trang 18printf(" cat toc ");
Trang 19Tho ngu khach vao Tho day cat toc cat xong Tho ngu khach vao Tho day cat tockhach vao cat xong cat toc khach vao cat xong cat toc cat xong Tho ngu
* Như vậy các tiến trình đã được điều độ đúng
F Bathroom problem
+ Bài toán:
• Một phòng tắm phục vụ cho cả nam và nữ nhưng chỉ phục vụ cho nam (hoặc
nữ ) trong một thời điểm nhất định
• Nếu phòng tắm chưa có người thì ai cũng có thể vào
• Nếu phòng tắm đang được sử dụng thì chỉ có người cùng giới tính với ngườitrong phòng tắm mới có thể vào
• Số lượng người sử dụng phòng tắm trong một đơn vị thời gian là có giới hạn( trong trường hợp này ta giả sử là 5 người)
+ Yêu cầu:
• Có 2 kiểu tiến trình male() và female()
• Mỗi tiến trình ở trong bathroom một khoảng thời gian ngẫu nhiên
+ Cài đặt
int m=0; // Số nam trong phòng tắm
fm=0; // Số nữ trong phòng tắm
Khởi tạo semaphore
room=1; // Nếu phòng tắm trống thì room=0;
maleMultiplex=5; // Khi có 1 người là nam vào phòng tắm thì giảm
maleMultiplex đi 1 và nếu có 1 người là nam ra khỏiphòng tắm thì tăng maleMultiplex lên 1
femaleMultiplex=5; // Tương tự như maleMultiplex nhưng với điều kiện người
ra ( vào) phòng tắm là nữ
turnstile=1; // Giảm đi 1 khi có tiến trình xin vào phòng tắm Dùng để điều độ
tránh tình trạng đói CPU của tiến trình male hoặc female
mutex1=1; // Điều độ biến đếm m;
Trang 20mutex2=1; // Điều độ biến đếm fm;
mutex=1; // Điều độ quyền truy cập file văn bản in kết quả
Trang 21WaitForSingleObject(femaleMultiplex,INFINITE);WaitForSingleObject(mutex,INFINITE);
f=fopen("text","at");
fprintf(f,"Nu vao ");
fclose(f);
ReleaseSemaphore(mutex,1,NULL);
Trang 22// Tạo thời gian ngẫu nhiên sử dụng phòng tắm t=rand()%5000;
fm;
if (fm==0) ReleaseSemaphore(room,1,NULL); ReleaseSemaphore(mutex2,1,NULL);
mutex = CreateSemaphore(NULL,1, 1, NULL);
room = CreateSemaphore(NULL,1, 1, NULL);
turnstile = CreateSemaphore(NULL,1, 1, NULL);
mutex1 = CreateSemaphore(NULL,1, 1, NULL);
mutex2 = CreateSemaphore(NULL,1, 1, NULL);
femaleMultiplex = CreateSemaphore(NULL,5, 5, NULL);maleMultiplex = CreateSemaphore(NULL,5, 5, NULL);for (i=0; i<10; ++i)
Trang 23h1[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)male,NULL, 0, &Id);
for (i=0; i<10; ++i)
h2[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)female,NULL, 0, &Id);
WaitForMultipleObjects(10, h1, TRUE, INFINITE);
WaitForMultipleObjects(10, h2, TRUE, INFINITE);
getch();
return 0;
}
+ Một kết quả chạy khi chạy chương trình:
Nam vao Nam vao Nam vao Nam vao Nam vao Nam ra Nam vao Nam ra Nam vaoNam ra Nam vao Nam ra Nam ra Nam vao Nam vao Nam ra Nam ra Nam ra Nam
ra Nam ra Nu vao Nu vao Nu vao Nu vao Nu vao Nu ra Nu ra Nu vao Nu ra Nu ra
Nu vao Nu ra Nu vao Nu vao Nu vao Nu ra Nu ra Nu ra Nu ra Nu ra Nam vaoNam vao Nam vao Nam vao Nam vao
* Như vậy ta thấy cách điều phối này đảm bảo sự công bằng nhưng không khaithác được tối đa khả năng phục vụ của phòng tắm Ví dụ: Khi có ít hơn 5 ngườiđàn ông trong phòng tắm, 1 người phụ nữ đến chờ thì những người đàn ông đếnsau người phụ nữ này cũng sẽ phải chờ trong khi vẫn còn chỗ trống trong phòngtắm
G Producer Consumer
+ Bài toán
• Đồng bộ hóa nhiều Producer , nhiều consumer dùng đèn hiệu
+ Yêu cầu:
• Producer sản xuất ra cần nào consumer sã tiêu thụ cần đấy
• Điều hòa count để chi có duy nhất 1 tiến trình truy cập nó tại 1 thời điểm
• Đồng bộ hóa trong mỗi Producer và consumer
Trang 24+ Khởi tạo :
• Đèn empty xem buffer rỗng hay không Khởi tạo là max = kích thước buffer,
và giá trị cực đại cũng là max
• Đèn full kiểm tra bufer đầy hay không Khởi tạo là 0 và cực đại là max kíchthước buffer
• Đèn mutex điều phối các tiến trình trong 1 producer , consumer Khi cónhiều producer và consumer Khởi tạo là 1 và cực đại là 1
• Đèn s điều phối count, sao cho tại một thời điểm chỉ có 1 tiến trình đượcdùng count Khởi tạo là 1 và cực đại là 1
in=(in+1)%max;
}
ReleaseSemaphore(mutex,1,NULL);
Trang 26HANDLE Producer[maxProducer];
HANDLE Consumer[maxConsumer];
DWORD Id;
int m,n,i;
cout<<"Nhap so luong cua Producer :"; cin>>n;
cout<<"nhap so luong cua Consumer :"; cin>>m;
Trang 27 5 triết gia ăn tối quanh một bàn tròn
• Trước mỗi triết gia có một đĩa mì
• Giữa hai đĩa kề nhau có một cái dĩa
Các triết gia thực hiện luân phiên, liên tục hai việc: Ăn và Nghĩ
Mỗi triết gia cần 2 cái dĩa để ăn
• Chỉ lấy một dĩa tại một thời điểm
• Cái bên trái trước rồi cái bên phải
Ăn xong để dĩa vào vị trí cũ
Viết chương trình đồng bộ bữa tối 5 triết gia
+ Khởi tạo semaphore
Các fork bằng 1 và giá trị tối đa là 1
Trang 29triet gia 3 nghi triet gia 4 lay dia 4 va 0 triet gia 2 nghi
triet gia 1 lay dia 2 va 1 triet gia 3 lay dia 4 va 3 trietgia 4 nghi triet gia 0 lay dia 0 va 1
I Bài toán tạo phân tử H2O
• Có 2 kiểu tiến trình (luồng): oxygen và hydrogen
• Để kết hợp các tiến trình thành phân tử nước, cần 1 ba-ri-e để các tiếntrình phải đợi cho tới khi một phân tử nước sẵn sàng được tạo ra
• Khi mỗi tiến trình vượt qua ba-ri-e, nó phải kích hoạt liên kết
• Tất cả các tiến trình trong cùng một phân tử nước phải tạo liên kết,trước khi một tiến trình của phân tử nước khác gọi tới thủ tục tạo liênkết
+ Khởi tạo:
int oxygen=0; // Số lượng nguyên tử oxy sản xuất được
Trang 30hydrogen=0; // Số lượng nguyên tử hydro sản xuất được.
int oxygen=0, hydrogen=0;
HANDLE mutex, oxyqueue, hydroqueue;
void Oxygen()
{while (1) {
WaitForSingleObject(mutex,INFINITE);
// Tạo 1 nguyên tử oxy
oxygen+=1; printf("Tao oxy ");
// Khi chưa tạo được liên kết thì nguyên tử phải chờ
else { printf("Oxy cho "); ReleaseSemaphore(mutex,1,NULL);} // Nạp 1 nguyên tử oxy vào hàng đợi oxyqueue
Trang 31// Tạo 1 nguyên tử hydro
hydrogen+=1; printf("Tao hydro ");
// Khi chưa tạo được liên kết thì nguyên tử phải chờ
else {printf("Hydro cho "); ReleaseSemaphore(mutex,1,NULL);} // Nạp 1 nguyên tử hydro vào hàng đợi hydroqueue
Trang 32int i=0,j=0,k;
srand(time(0));
mutex = CreateSemaphore(NULL,1, 1, NULL);
oxyqueue = CreateSemaphore(NULL,0, 10, NULL);
hydroqueue = CreateSemaphore(NULL,0, 10, NULL);
do {
k=rand()%50;
if ((k%2==0)&&(i<10)) {h1[i] = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)Oxygen, NULL, 0, &Id); ++i;} else if (j<20) { h2[j] = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)Hydrogen, NULL, 0, &Id);++j;}
} while ((j<20)&&(i<10));
WaitForMultipleObjects(10, h1, TRUE, INFINITE);
WaitForMultipleObjects(20, h2, TRUE, INFINITE);
getch();
return 0;
}
+ Một kết quả khi chạy chương trình:
Tao oxy Oxy cho Tao hydro Hydro cho Tao hydro Hydro sinh lien ket Oxy sinhlien ket Hydro sinh lien ket Tao hydro Hydro cho Tao oxy Oxy cho Tao oxy Oxycho Tao oxy Oxy cho Tao hydro Hydro sinh lien ket Hydro sinh lien ket Oxy sinhlien ket Tao oxy Oxy cho Tao oxy Oxy cho Tao oxy Oxy cho Tao hydro Hydrocho Tao hydro Hydro sinh lien ket Hydro sinh lien ket Oxy sinh lien ket Tao hydroHydro cho Tao oxy Oxy cho Tao hydro Hydro sinh lien ket Oxy sinh lien ketHydro sinh lien ket Tao hydro Hydro cho Tao hydro Hydro sinh lien ket Hydrosinh lien ket Oxy sinh lien ket Tao oxy Oxy cho Tao oxy Oxy cho
* Kết quả cho thấy các tiến trình đã được điều độ đúng đắn ( ngay khi có đủ 1nguyên tử oxy và 2 nguyên tử hydro thì lập tức tạo liên kết sinh ra phân tử H2O)