Chương 1 Tổng quan

1.1 Chương trình quản lý phòng máy bao gồm những gì?

Trong quá trình khảo sát các chương trình quản lý phòng máy đang sử dụng

tại Việt Nam, chúng em tạm phân loại các yêu cầu đề ra là : các yêu cầu cần, các

yêu cầu đủ, và các yêu cầu mở rộng.

1.1.1 Các yêu cầu cần:

Bản thân chương trình quản lý máy thuê Internet phải có khả năng tính tiền

cước hợp lý cho người sử dụng. Người thuê máy cần cảm thấy việc tính cước đúng

và làm họ hài lòng. Ngoài ra, nếu phòng máy còn có phục vụ món ăn, dịch vụ như:

tạp chí, sách báo… thì một yêu cầu cần khác là cần tính phí phục vụ cho người

dùng. Đối với người dùng, họ cảm thấy hài lòng khi việc phục vụ được nhanh

chóng và chu đáo.

1.1.2 Các yêu cầu đủ:

Ngoài hai yêu cầu trên, việc bảo mật bảo mật và kiểm duyệt nội dung web

cũng rất quan trọng do nó cũng ảnh hưởng một phần đến việc kinh doanh (chẳng

hạn, thể gây ảnh hưởng uy tín phòng máy khi lướt web đen…). Vì vậy, các yêu cầu

kiểm soát hệ thống máy khách được đặt ra như quan sát màn hình máy khách, đọc

nội dung người dùng gõ…

1.1.3 Các yêu cầu mở rộng:

Ngoài các dạng yêu cầu trên, các yêu cầu còn lại là các yêu cầu mở rộng.

Thật ra, các yêu cầu mở rộng chỉ có tính tương đối. Tùy thuộc yêu cầu đặt ra cho

phần mềm mà ta có thể xem xét thêm các yêu cầu mở rộng như là yêu cầu đủ. Các

yêu cầu mở rộng thường thấy là : lọc liên kết web, nội dung web, nhắn tin di động,

chat nội bộ giữa các máy khách với nhau, đa ngôn ngữ…

1

1.2 Các chương trình quản lý phòng máy hiện nay ở Việt

Nam.

1.2.1 Cyber Station Manager

Cyber Station Manager là phần mềm quản lý khách hàng, thời gian sử

dụng máy trạm, điều khiển máy trạm do công ty trách nhiệm hữu hạn Đan Thanh

viết. Chương trình có các chức năng chính:

o Quản lý thông tin các máy trạm

o Quản lý thông tin các hội viên

o Quản lý hóa đơn

1.2.2 Internet Café Software:

Do công ty PA Việt Nam 65 đường Sư Vạn Hạnh nối dài Q.10 Tp. Hồ

Chí Minh viết. Các tính năng chính:

o Quản lý thông tin các máy trạm

1.2.3 iSystem 3.0 :

Hệ phần mềm chuyên nghiệp cho máy dịch vụ game – Internet, gồm

hai phần :

o iSystem hỗ trợ quản trị mạng từ bất cứ máy nào trong mạng nội bộ, hỗ trợ lọc

web đen, biên tập danh bạ web, phân vùng khởi động, hỗ trợ kết nối Internet

và ADSL.

o iNetman hỗ trợ quản lý đồng thời nhiều loại dịch vụ (game, Internet…) và

quản lý bán hàng.

Do công ty TBNet 111 Lý Thường Kiệt Tp Thái Bình – tỉnh Thái Bình.

1.2.4 EasyCafe :

Do công ty Tinasoft tại Thổ Nhĩ Kỳ viết.

Các chức năng:

o Quản lý thông tin các máy trạm.

2

o Quản lý thông tin các hội viên.

o Quản lý hóa đơn.

o Lọc thông tin.

o Nhắn tin di dộng.

o Điều khiển từ xa các máy trạm.

1.3 Các ưu khuyết điểm của các chương trình trên.

1.3.1 Cyber Station Manager

Ưu điểm :

Phần mềm quản lý chi tiết việc phân loại khách hàng gồm : hội viên, khách

vãng lai và người quản trị cả Server và Client.

Các cách tính cước cho người dùng phong phú: trả tiền trước, trả tiền sau,

cộng dồn tiền cước các máy(cho phép đổi máy sử dụng khi đang sử dụng máy nào

đó). Cộng thêm thời gian sử dụng miễn phí cho khách. Thêm phí tự động cho khách

khi khách có yêu cầu.

Khuyết điểm:

Cài đặt phức tạp( do dùng MySQL).

Sử dụng Tiếng Việt không dấu.

Các chức năng quản lý máy trạm đơn giản.

Các chức năng điều khiển từ xa còn ít.

1.3.2 Internet Café Software

Ưu điểm :

- Giao diện đơn giản, dễ dùng. Có thể chuyển đổi máy cho khách

hàng.

- Màn hình screen che khá hiệu quả .

Khuyết điểm:

- Các chức năng không đầy đủ( Chương trình chỉ có phần tính cước,

in báo biểu).

3

- Phải đổi tên máy ngay khi bắt đầu sử dụng bên phía Server. Máy

phải khởi động lại.

1.3.3 iSystem 3.0

Ưu điểm :

- Giao diện đơn giản, dễ dùng. Có thể chuyển đổi máy cho khách

hàng.

Khuyết điểm:

- Mặc dù có một số chức năng quản trị máy từ xa, nhưng vẫn còn rất ít

(chỉ có tắt máy, nhắn tin từ máy chủ).

- Phải đổi tên máy ngay khi bắt đầu sử dụng bên phía Server. Máy

phải khởi động lại.

1.3.4 Easy Café:

Ưu điểm :

- Có gần như đầy đủ tất cả các chức năng quản lý cần thiết và mở

rộng.

- Hỗ trợ đa ngôn ngữ.

- Có thể xem đây phần mềm điển hình về việc quản lý các máy trạm ở

phòng cho thuê dịch vụ Internet.

Khuyết điểm:

- Vì phải quản lý chi tiết mọi thứ nên giao diện phức tạp, khó dùng.

- Không hỗ trợ tiếng Việt mặc dù là phần mềm đa ngôn ngữ.

4

Chương 2 Xây dựng chương trình quản lý phòng máy

2.1 Xác định yêu cầu:

2.1.1 Các yêu cầu chức năng:

Xây dựng phần mềm quản lý phòng thuê Internet, chương trình có

yêu cầu quản lý những tính năng cần là:

Các tính năng cần là:

Tính cước sử dụng máy

Tính cước phục vụ món

Quản lý báo cáo

Các tính năng đủ là:

Kiểm soát các họat động máy khách và nội dung sử dụng của người

dùng

2.1.2 Các yêu cầu phi chức năng:

2.2 Phân tích thiết kế hệ thống:

2.2.1 Xây dựng Use Case:

2.2.1.1

Xác định Actor và Use Case phía Server:

Actor: Người sử dụng chương trình Server ở máy chủ - Người quản

lý.

Use Case:

Start Server: Chạy chương trình Server.

Login: Cho phép Client sử dụng máy tính với trạng thái

username=”anonymous” , password=””.

Logout: Không cho phép Client sử dụng máy tính.

Paid: Tính tiền người dùng.

5

Banner: Thông tin (các nội quy của phòng máy ) người quản

lý muốn cho khách hàng biết.

Report :

Report Debit: Thống kê các khách hàng nợ.

Report Daily: Thống kê các thông tin kết nối của các

máy khách hằng ngày.

Report Month: Thống kê tình trạng sử dụng các máy

theo tháng.

Option :

Manage Cafeteria: Người quản lý có thể xem, sửa hay

bổ sung các loại món ăn, thức uống.

Manage Kind of Food: Người quản lý có thể xem, sửa

hay bổ sung các món ăn, thức uống.

Manage Price Day: Người quản lý có thể xem, sửa hay

bổ sung giá truy cập internet theo ngày cụ thể.

Manage Debit: Người quản lý thêm vào cơ sở dữ liệu

khách hàng còn nợ.

Manage Member: Người quản lý có thể xem, sửa hay bổ

sung thành viên.

Administration:

Lock Key: Cho phép người quản lý có thể khóa tất cả

các phím hay một số phím trên một máy khách đang sử dụng.

Log Key: Cho phép người quản lý có thể ghi nhận lại

các phím khách hàng sử dụng trên một máy khách đang sử dụng.

Manage Application: Cho phép người quản lý có thể

biết được các ứng dụng chạy trên máy khách, và người quản lý cũng có thể bật hay

tắt một ứng dụng nào đó.

Manage Service: Cho phép người quản lý có thể biết

được các service chạy trên máy khách, và người quản lý cũng có thể thay đổi loại

6

khởi động (Automatic, Manual hay Disable) hay cũng có thể trạng thái service(Start

hay Stop).

Manage Remote Computer: Cho phép người quản lý có

thể Logout, Restart hay Shutdown một máy khách bất kỳ hay cho tất cả các máy

theo các tinh chỉnh về thời gian thực hiện.

Send Message: Cho phép người quản lý có thể gởi tin

nhắn đến một máy khách bất kỳ hay cho tất cả các máy.

Snapshot: Cho phép người quản lý có thể chụp hình tĩnh

hay hình động máy khách. Khi chụp tĩnh, tối đa chụp được 4 máy khách. Khi chụp

động thì chụp được 1 máy khách.

2.2.1.2

Xác định các Actor và Use Case phía Client:

Actor: Người sử dụng chương trình Screen.

Use Case:

Connect: thực hiện kết nối với Server để vào trạng thái chờ.

Login Member: thực hiện login vào Server dưới hình thức

Member.

Actor: Người sử dụng chương trình Client.

Use Case:

Connect: thực hiện kết nối với Server để vào trạng thái sử

dụng.

Order: thực hiện đặt món ăn từ danh sách với Server.

2.2.1.3 Mô hình Use Case:

2.2.1.3.1 Phía Server

7

Start Server (from Use Case)

Login (from Use Case)

Logout (from Use Case)

Paid (from User Case)

Administration (from User)

User

Set Banner (from Use Case)

Change Option (from User)

Report (from Use Case)

Service order (from User)

Month Report (from User)

Daily Report (from User)

Debit Report (from User)

User

Hình 2-1 Mô hình Use Case tổng quát

Hình 2-2 Mô hình Use Case Report

8

Manage Price Day (from User)

Manage Debit (from User)

Manage Kind of Food (from User)

User

Manage Cafeteria (from User)

Manage Member (from User)

Log Key (from User)

Lock Key (from User)

Manage Application (from User)

User

Snap Shot (from User)

Manage Service (from User)

Send Message (from User)

Manage Remote Computer (from User)

Apply Policy (from User)

Hình 2-3 Mô hình Use Case Manage

Hình 2-4 Mô hình Use Case Administrator

9

2.2.1.3.2 Phía Client:

2.2.1.3.2.1 Screen:

Connect (from User)

Login Member (from User)

User

Hình 2-5 Mô hình Use case Screen

2.2.1.3.2.2 Client:

Connect

Order (from User)

User

Hình 2-6 Mô hình Use case Client

10

2.2.2 Đặt tả Use Case:

2.2.2.1

Phía Server:

2.2.2.1.1 Start Server Use Case:

Tên Use Case: Start Server.

Mô tả : Server khởi động và lắng nghe kết nối.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Người dùng khởi động chương trình.

+ Chương trình sẽ thực hiện việc mở cơ sở dữ liệu.

+ Kiểm tra thông tin kết nối .

+ Thực hiện việc lắng nghe các kết nối từ máy khách.

- Dòng sự kiện khác:

+ Nếu có lỗi về việc mở cơ sở dữ liệu thì chương trình sẽ báo

lỗi và thoát ra khỏi chương trình.

+ Nếu không có thông tin về số lượng máy có thể kết nối thì sẽ

xuất thông báo yêu cầu nhập thông tin.

+ Nếu lần trước Server bị “chết”, thì bây giờ Server sẽ kiểm tra

lại kết nối từ các máy khách.

- Điều kiện tiên quyết:

+ Phải có cơ sở dữ liệu.

- Điều kiện bổ sung :

+ Chương trình phải đăng ký các Active X về List View.

- Điểm mở rộng:

+ Không có.

2.2.2.1.2 Login Use Case :

Tên Use Case : Login.

Mô tả :

11

Người quản lý có thể cho máy khách login với tư cách là anonymous.

Dòng sự kiện :

-Dòng sự kiện chính :

+ Use case này bắt đầu khi người quản lý chọn Login.

+ Server kiểm tra xem máy khách có đang ở trạng thái chờ ?

+ Nếu hợp lệ Server gởi thông điệp đến máy khách.

+ Client nhận thông điệp sẽ tắt màn hình Screen và gởi thông

điệp chấp nhận về Server.

+ Server nhận thông điệp sẽ cho phép khách hàng ở máy khách

có thể sử dụng với tư cách anonymous. Chương trình bắt đầu

tính tiền cho khách hàng từ lúc này cho đến lúc khách hàng kết

thúc sử dụng

- Dòng sự kiện khác :

+ Nếu Server kiểm tra máy khách không phải ở trạng thái chờ

thì không cho Login.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Máy chuyển từ trạng thái chờ sang trạng thái sử dụng.

- Điểm mở rộng:

+ Không có.

2.2.2.1.3 Logout Use Case:

Tên Use Case : Logout.

Mô tả : Kết thúc việc khách hàng sử dụng máy khách.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi khách hàng chọn Logout.

+ Server gởi thông điệp cho Client, cập nhật lại database.

12

+ Client nhận thông điệp và tắt hết các chương trình đang sử dụng.

+ Client bật màn hình che( màn hình Screen).

+ Màn hình che connect lại với Server.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Client phải Login vào Server trước.

- Hậu điều kiện:

+ Máy chuyển từ trạng thái sử dụng sang trạng thái chờ.

- Điểm mở rộng:

+ Không có .

2.2.2.1.4 Paid Use Case:

Tên Use Case : Paid.

Mô tả : Kết thúc việc khách hàng sử dụng máy khách và tính tiền.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý chọn Paid.

+ Server gởi thông điệp cho Client.

+ Client nhận thông điệp và tắt hết các chương trình đang sử dụng.

+ Client bật màn hình che( màn hình Screen).

+ Server tính tiền sử dụng và tiền các dịch vụ liên quan và xuất ra

màn hình.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Client phải Login vào Server trước.

- Hậu điều kiện:

+ Máy chuyển từ trạng thái sử dụng sang trạng thái chờ.

13

- Điểm mở rộng:

+ Không có.

2.2.2.1.5 Service Order Use Case:

Tên Use Case : Service Order.

Mô tả : Phục vụ món ăn cho khách hàng.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi khách hàng yêu cầu phục vụ món ăn thức

uống.

+ Người quản lý chọn máy khách mà khách hàng yêu cầu phục vụ.

Khi đó danh sách các món ăn, thức uống mà khách hàng yêu cầu hiện ra.

+ Người quản lý phục vụ lần lượt các món ăn. Lúc đó, tiền dịch vụ

được cập nhật vào trong tiền sử dụng máy.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Máy khách đang ở trạng thái sử dụng.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.6 Set Banner Use Case:

Tên Use Case: Banner.

Mô tả : Thông báo các quy định về sử dụng phòng máy cho khách hàng.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý chọn Set Banner.

+ Nhập các quy định mà người quản lý muốn khách hàng cần biết.

14

+ Server gởi thông điệp đến tất cả các máy khách có kết nối với

Server.

+ Client nhận thông điệp sẽ cập nhật thông báo.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Máy khách đang ở trạng thái sử dụng.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.7 Daily Report Use Case:

Tên Use Case: Daily Report.

Mô tả: Hiển thị thông tin kết nối của các máy khách hằng ngày.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý chọn thống kê hàng ngày.

+ Chương trình đọc cơ sở dữ liệu từ bảng Daily Report và xuất ra

màn hình.

- Dòng sự kiện khác:

+ Nếu có lỗi cơ sở dữ liệu thì chương trình sẽ hiển thị thông báo.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.8 Month Report Use Case:

15

Tên Use Case: Daily Report

Mô tả: Hiển thị thông tin tiền của máy khách kiếm được trong cả tháng

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý chọn Month Report.

+ Chương trình đọc cơ sở dữ liệu từ bảng Month Report và xuất ra

màn hình.

- Dòng sự kiện khác:

+ Nếu có lỗi cơ sở dữ liệu thì chương trình sẽ hiển thị thông báo.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.9 Debit Report Use Case:

Tên Use Case: Debit Report.

Mô tả: Hiển thị danh sách các khách hàng còn nợ.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý chọn biểu tượng Debit

Report.

+ Chương trình đọc cơ sở dữ liệu từ bảng Debit Report và xuất ra

màn hình.

+ Khi người dùng chọn một khách hàng nợ thì thông tin chi tiết về

người khách nợ đó sẽ xuất ra màn hình.

- Dòng sự kiện khác:

+ Nếu có lỗi cơ sở dữ liệu thì chương trình sẽ hiển thị thông báo.

16

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.10 Manage Kind of Food Use Case:

Tên Use Case: Kind of Food.

Mô tả : Người quản lý có thể xem, sửa hay bổ sung các loại món ăn, thức

uống.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case này bắt đầu khi người quản lý chọn chức năng

quản lý loại món ăn, thức uống.

+ Màn hình xuất danh sách các loại món ăn, thức uống.

+ Người quản lý có thể chọn chức năng edit để sửa đổi

thông tin: luồng sự kiện phụ là sửa đổi một loại thức ăn

được kích hoạt.

+ Người quản lý có thể chọn chức năng Add new để thêm

thông tin luồng sự kiện phụ là thêm một loại thức ăn được

kích hoạt.

+ Người quản lý có thể chọn chức năng Delete để xóa

thông tin: luồng sự kiện phụ là xóa một loại thức ăn được

kích hoạt.

Sửa đổi một loại thức ăn:

+ Chọn loại thức ăn.

+ Nhập mới tên loại thức ăn.

+ Chọn chức năng Edit.

17

+ Chương trình sẽ cập nhật lại cơ sở dữ liệu.

Thêm một loại thức ăn:

+ Nhập tên loại thức ăn.

+ Chọn chức năng Add.

+ Chương trình sẽ cập nhật lại cơ sở dữ liệu.

Xóa một lọai thức ăn:

+ Chọn loại thức ăn.

+ Chọn chức năng Delete.

+ Chương trình sẽ cập nhật lại cơ sở dữ liệu.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.11 Manage Cafeteria Use Case:

Tên Use Case: Manage Cafeteria.

Mô tả: Người quản lý có thể xem, sửa hay bổ sung các món ăn.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case này bắt đầu khi người quản lý chọn chức năng

quản lý thức ăn, thức uống.

+ Màn hình xuất danh sách các món ăn, thức uống.

+ Người quản lý có thể chọn chức năng edit để sửa đổi

thông tin: luồng sự kiện phụ là sửa đổi thức ăn, thức uống

được kích hoạt.

18

+ Người quản lý có thể chọn chức năng Add new để thêm

thông tin luồng sự kiện phụ là thêm thức ăn, thức uống

được kích hoạt.

+ Người quản lý có thể chọn chức năng Delete để xóa

thông tin:luồng sự kiện phụ là xóa thức ăn, thức uống được

kích hoạt.

Sửa đổi thức ăn, thức uống:

+ Chọn thức ăn, thức uống.

+ Nhập mới các thông tin cần thiết như tên , giá

cả…

+ Chọn chức năng Edit.

+ Chương trình sẽ cập nhật lại cơ sở dữ liệu.

Thêm thức ăn, thức uống:

+ Nhập mới các thông tin cần thiết như tên , giá

cả… của thức ăn, thức uống.

+ Chọn chức năng Add.

+ Chương trình sẽ cập nhật lại cơ sở dữ liệu.

Xóa thức ăn, thức uống:

+ Chọn thức ăn, thức uống.

+ Chọn chức năng Delete.

+ Chương trình sẽ cập nhật lại cơ sở dữ liệu.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

19

2.2.2.1.12 Manage Price Day Use Case:

Tên Use Case: Manage Price Day.

Mô tả: Người quản lý có thể xem, sửa hay bổ sung giá truy cập internet theo

ngày cụ thể.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case này bắt đầu khi người quản lý chọn chức năng

quản lý giá dịch vụ.

+ Người quản lý chọn ngày cần quản lý.

+ Màn hình xuất giá truy cập 7 ngày trong tuần mà ngày đã

chọn thuộc vào.

+ Người quản lý chọn các giờ rồi chọn chức năng edit để

sửa đổi giá cả.

- Dòng sự kiện khác:

+ Nếu không chọn thì giá cả là mặc định.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.13 Manage Debit Use Case:

Tên Use Case: Manage Debit

Mô tả : Người quản lý thêm vào cơ sở dữ liệu khách hàng còn nợ

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case này bắt đầu khi người quản lý chọn chức năng

quản lý khách hàng nợ.

20

+ Màn hình sẽ hiển thị các thông tin cho người quản lý

nhập mới.

+ Người quản lý chọn máy mà khách hàng đã sử dụng, khi

đó danh sách các giờ Login vào máy đó sẽ xuất hiện. Người

quản lý chọn một trong số các giờ bắt đầu đó.

+ Sau đó nhập vào một số thông tin (bao gồm Tên, Địa chỉ,

Số điện thoại, tiền trả trước ….).

+ Sau khi nhập xong, chương trình sẽ lưu xuống cơ sở dữ

liệu

- Dòng sự kiện khác:

+ Không có

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.14 Manage Member Use Case:

Tên Use Case :Manage Member.

Mô tả : Người quản lý

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case này bắt đầu khi người quản lý chọn chức năng

quản lý thành viên của phòng máy.

+ Chương trình xuất hiện cửa sổ mới có danh sách các

thành viên.

21

+ Người quản lý có thể chọn chức năng edit để sửa đổi

thông tin: luồng sự kiện phụ là sửa đổi thành viên được

kích hoạt.

+ Người quản lý có thể chọn chức năng Add new để thêm

thông tin luồng sự kiện phụ là thêm thành viên được kích

hoạt.

+ Người quản lý có thể chọn chức năng Delete để xóa 1

record luồng sự kiện phụ là xóa thành viên được kích hoạt.

Sửa đổi thành viên:

+ Chọn thành viên.

+ Nhập mới các thông tin cần thiết như tên , địa

chỉ, số điện thoại…

+ Chọn chức năng Edit.

+ Chương trình cập nhật các thông tin thay đổi

vào cơ sở dữ liệu.

Thêm thức ăn, thức uống:

+ Nhập mới các thông tin cần thiết như tên , địa

chỉ, số điện thoại…của thành viên.

+ Chọn chức năng Add.

+ Chương trình lưu thông tin vào cơ sở dữ liệu.

Xóa thức ăn, thức uống:

+ Chọn thành viên.

+ Chọn chức năng Delete.

+ Chương trình xóa thông tin trong cơ sở dữ liệu.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

22

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.15 Lock Keys Use Case :

Tên Use Case: Lock Keys.

Mô tả : Cho phép người quản lý khóa các phím của máy khách.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý yêu cầu khóa phím.

+ Người quản lý chọn máy khách mà người quản lý muốn

khóa.

+ Chọn chế độ khóa là khóa tất cả phím, khóa phím F1-

>F2, khóa phím A->Z, khóa phím số , khóa phím dấu, khóa

phím hỗ trợ, khóa phím bất kỳ.

+ Khi đó Server sẽ gởi thông điệp đến máy khách, máy

khách nhận thông điệp sẽ thực hiện khóa phím tương ứng

với chế độ khóa.

+ Nếu thực hiện thành công thì máy khách sẽ gởi thông

điệp báo cho Server là khóa thành công.

+ Để kết thúc việc khóa, người quản lý chọn Mở khóa tất cả

+ Khi đó Server sẽ gởi thông điệp đến máy khách, máy

khách nhận thông điệp sẽ thực hiện mở khóa tất cả các

phím.

+ Nếu thực hiện thành công thì máy khách sẽ gởi thông

điệp báo cho Server là mở khóa thành công.

- Dòng sự kiện khác:

+ Nếu không thành công thì máy khách gởi thông điệp

cho Server báo là không thành công.

23

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.16 Log Keys Use Case :

Tên Use Case: Log Keys.

Mô tả : Cho phép người quản lý có thể ghi nhận lại các phím khách hàng sử

dụng trên máy khách.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý yêu cầu ghi nhận

phím.

+ Người quản lý chọn máy khách mà người quản lý muốn

ghi nhận phím.

+ Chọn bắt đầu ghi nhận.

+ Khi đó Server sẽ gởi thông điệp đến máy khách, máy

khách nhận thông điệp sẽ ghi nhận các phím người dùng đã

nhấn.

+ Người quản lý muốn xem những thông tin đã ghi nhận, sẽ

dừng tiến trình ghi nhận thông tin. Khi đó Server sẽ gởi

thông điệp đến máy khách, máy khách nhận thông điệp sẽ

thực hiện gởi thông tin ghi nhận cho Server

+ Nếu nhận thông tin thành công Server sẽ thông báo thành

công.

+ Người quản lý có thể xem thông tin ghi nhận.

- Dòng sự kiện khác:

24

+ Không có.

- Điều kiện tiên quyết:

+ Máy khách phải đang ở trạng thái sử dụng.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.17 Manage Application Use Case:

Tên Use Case: Manage Application.

Mô tả : Cho phép người quản lý có thể biết được các ứng dụng chạy trên

máy khách, và người quản lý cũng có thể bật hay tắt một ứng dụng nào đó.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý yêu cầu quản lý ứng

dụng trên máy khách.

+ Người quản lý chọn máy khách mà người quản lý muốn

xem danh sách các ứng dụng.

+ Nếu người quản lý chọn xem danh sách các ứng dụng:

Server gởi thông điệp yêu cẩu danh sách đến máy khách,

máy khách thực hiện việc ghi lại danh sách các ứng dụng

đang chạy ở máy khách và gởi về Server.

+ Nếu người quản lý chọn bật một ứng dụng: màn hình yêu

cầu nhập các thông tin cần thiết (như tên ứng dụng, đường

dẫn…) để bật ứng dụng, và Server gởi yêu cầu đến máy

khách. Máy khách nhận thông điệp sẽ bật ứng dụng tương

ứng.

25

+ Nếu người quản lý chọn tắt một ứng dụng: người quản lý

chọn một ứng dụng từ danh sách, Server gởi yêu cầu đến

máy khách. Máy khách nhận thông điệp sẽ tắt ứng dụng.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.18 Manage Service Use Case:

Tên Use Case: Manage Service.

Mô tả : Cho phép người quản lý có thể biết được các service chạy trên máy

khách, và người quản lý cũng có thể thay đổi loại khởi động( Automatic,

Manual hay Disable) hay cũng có thể thay đổi trạng thái service( Start hay

Stop).

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý yêu cầu quản lý dịch

vụ trên máy khách.

+ Người quản lý chọn máy khách mà người quản lý muốn

xem thông tin service.

+ Nếu người quản lý chọn xem danh sách các dịch vụ:

Server gởi thông điệp yêu cầu danh sách đến máy khách,

máy khách thực hiện việc ghi lại danh sách các dịch vụ

đang chạy ở máy khách và gởi về Server.

26

+ Nếu người quản lý chọn thay đổi loại khởi động dịch vụ:

màn hình yêu cầu nhập loại tương ứng để thay đổi. Server

gởi yêu cầu đến máy khách. Máy khách nhận thông điệp sẽ

thay đổi tương ứng.

+ Nếu người quản lý chọn thay đổi trạng thái dịch vụ: màn

hình yêu cầu chọn trạng thái tương ứng để thay đổi. Server

gởi yêu cầu đến máy khách. Máy khách nhận thông điệp sẽ

thay đổi tương ứng.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.19 Send Message Use Case:

Tên Use Case: Send Message.

Mô tả : Cho phép người quản lý có thể gởi tin nhắn đến một máy khách bất

kỳ hay cho tất cả các máy..

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý yêu cầu gởi tin nhắn.

+ Gởi đến một máy: người quản lý chọn máy khách mà

người quản lý muốn gởi thông điệp.

+ Nhập thông điệp và yêu cầu Server gởi thông điệp đến

máy đã chọn.

27

+ Gởi đến tất cả các máy: yêu cầu Server gởi thông điệp

đến tất cả các máy.

+ Máy khách nhận thông điệp sẽ xuất ra màn hình.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.20 Manage Remote Computer:

Tên Use Case: Manage Remote Computer.

Mô tả : Cho phép người quản lý có thể Logout, Restart hay Shutdown một

máy khách bất kỳ hay cho tất cả các máy.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người quản lý yêu cầu Logout,

Restart hay Shutdown.

+ Nếu người quản lý yêu cầu Logout: luồng sự kiện phụ

yêu cầu Logout được kích hoạt.

+ Nếu người quản lý yêu cầu Resstart: luồng sự kiện phụ

yêu cầu Resstart được kích hoạt.

+ Nếu người quản lý yêu cầu Shutdown: luồng sự kiện phụ

yêu cầu Shutdown được kích hoạt.

Logout:

+ Người quản lý có thể chọn một máy hay

tất cả máy.

28

+ Người quản lý có thể nhập thời gian.

Sau thời gian đó chương trình sẽ thực hiện

logout.

+ Người quản lý yêu cầu Logout. Server

sẽ gởi thông điệp đến máy khách yêu cầu

máy khách thực hiện logout.

tương tự cho Restart và Shutdown

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

+ Không có.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.1.21 SnapShot Use Case:

Xem phần kỹ thuật.

2.2.2.2

Phía Client:

2.2.2.2.1 Screen

2.2.2.2.1.1

Screen Connect Use Case:

Tên Use Case : Screen Connect.

Mô tả : Máy khách thực hiện kết nối với Server để vào trạng thái chờ.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi máy khách bắt đầu chạy chương trình.

29

+ Chương trình kiểm tra thông tin kết nối và gởi thông điệp

đến Server.

+ Nếu nhận được hồi đáp chấp nhận thì chương trình sẽ thực

hiện kết nối với Server và màn hình chờ bật lên( Use Case

thành công).

- Dòng sự kiện khác:

+ Nếu các thông tin kết nối không có ( như thông tin về tên

máy, địa chỉ IP SERVER, port ) thì sẽ nhập thông báo yêu cầu

nhập thông tin lại.

+ Nếu tên máy trùng với một tên máy đã kết nối trước vào

Server( do hồi đáp không chấp nhận của Server) thì cũng sẽ

nhập thông báo yêu cầu nhập thông tin lại.

+ Nếu kết nối không thành công thì sẽ báo lỗi.

- Điều kiện tiên quyết:

+ Server phải khởi động trước khi máy khách muốn kết nối vào

màn hình chờ.

- Hậu điều kiện:

+ Máy khách đang ở trạng thái down chuyển sang trạng thái

chờ.

- Điểm mở rộng:

+ Không có.

2.2.2.2.1.2 Login Member Use Case:

Tên Use Case : Login Member.

Mô tả: Máy khách thực hiện login vào Server dưới hình thức Member.

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi khách hàng bắt đầu đăng nhập vào

Server để sử dụng máy.

+ Khách hàng nhập thông tin bao gồm Username và Password.

30

+ Chương trình gởi thông điệp đến Server.

+ Nếu nhận được hồi đáp chấp nhận thì màn hình chờ tắt,

chương trình chính Client sẽ bật lên để tính giờ và khi đó

khách hàng có thể sử dụng được máy này.

- Dòng sự kiện khác:

+ Nếu nhận được hồi đáp từ chối thì màn hình screen vẫn

không bị tắt.

- Điều kiện tiên quyết:

+ Server phải khởi động trước.

+ Máy khách đang ở trạng thái chờ.

- Hậu điều kiện:

+ Máy khách đang ở trạng thái chờ chuyển sang trạng thái sử

dụng.

- Điểm mở rộng:

+ Không có.

2.2.2.2.2 Client

2.2.2.2.2.1 Client Connect Use Case:

Tên Use Case : Client Connect.

Mô tả: Máy khách thực hiện kết nối với Server để vào trạng thái sử dụng

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi người dùng login thành công vào

Server.

+ Chương trình kết nối với Server.

+ Server nhận được thông điệp kết nối sẽ bắt đầu gởi danh sách

các món ăn, banner cho Client.

+ Máy khách sẽ nhận thông điệp từ Server sẽ lưu trữ các thông

tin đó.

31

+ Máy khách xuất thông báo về nội quy sử dụng phòng máy.

- Dòng sự kiện khác:

+ Nếu kết nối không thành công thì sau 1 khoảng thời gian

máy khách sẽ tự động thực hiện kết nối lại với Server.

- Điều kiện tiên quyết:

+ Server phải khởi động trước khi máy khách muốn kết nối vào

màn hình chờ.

+ Máy khách đang ở trạng thái chờ.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.2.2.2.2 Order Use Case:

Tên Use Case : Order

Mô tả : Khách hàng có thể thực hiện đặt món ăn từ danh sách với Server

Dòng sự kiện :

- Dòng sự kiện chính :

+ Use case bắt đầu khi khách hàng yêu cầu phục vụ.

+ Danh sách các thức ăn, thức uống sẽ xuất hiện.

+ Khách hàng chọn các thông tin cần thiết như món ăn, số

lượng…

+ Khi khách hàng yêu cầu phục vụ các món mình đã chọn thì

máy khách sẽ gởi thông điệp cho Server.

+ Server nhận thông điệp sẽ lần lượt phục vụ các món ăn khách

hàng đã yêu cầu.

- Dòng sự kiện khác:

+ Không có.

- Điều kiện tiên quyết:

32

+ Server phải khởi động trước khi máy khách muốn kết nối vào

màn hình chờ.

+ Phía máy khách đang ở trong trạng thái sử dụng.

- Hậu điều kiện:

+ Không có.

- Điểm mở rộng:

+ Không có.

2.2.3 Thiết kế lớp trên Server:

2.2.3.1 Giao diện Server:

33

l

l

l

l

l

g D

l

l

g D

l

l

l

g D e c

g D

g D e u

l

t i

i r

i

g D h s a r

t

t r o p e R y

t

l i

C r e

b e D C

I

t f

g D r e n n a B C

t r o p e R h t n o M C

P u p n C

I

g D h s D t u p n I C

g D r e v r e S o f n I C

a V t u p n I C

a D C

A C

r e b m e M u p n C

g D y r o g e t a C t u p n I C

l

g D

t r o p e R

t i

b e D C

b a T n o i t a t S k r o W C

l

g D

l

t r o p e R

l i

a

t

e D

t i

i

g D r e v r e S e f a C C

b e D C

b a T e c v r e S C

i

b a T n m d A C

L S S e g a P b a T C

e g a P b a T t n e r a P C

b a T

i

t s L v r

S C

l r t

C b a T e s a B C

l

l

l r t

L S S

b a T

t

l r t

b a T g n

t s

i

i l

g D p u t r a S v r

C b a T n E C

p p A C

b a T g o L y e K C

b a T p a C r c S C

C b a T C

b a T k c o L y e K C

g g o L C

b a T e g a s s e M C

g D s u t a t S v r S g h C C

S g h C C

l

g D d d A y e K k c o L C

Hình 2-7 Thiết kế lớp giao diện Server

34

STT Tên lớp Kế thừa từ lớp Chức năng

dùng tự vẽ giao diện

1 CBaseTabCtrl CTabCtrl tab ctrl

dùng tô màu đỉnh Tab

theo màu nền 2 CEnTabCtrl CBaseTabCtrl

dùng Add Dialog (xem

1 dialog như một trang

của tab) 3 CTabCtrlSSL CEnTabCtrl

dùng để thể hiện

dialog như một trang

của Tab 4 CTabPageSSL CDialog

dùng để tô màu nền

5 CParentTabPage CTabPageSSL và gắn tooltip

giao diện để điều

khiển hoạt động máy

tính 6 CLoggingTab CParentTabPage

giao diện để khóa bàn

phím 7 CKeyLockTab CParentTabPage

giao diện dùng để ghi

8 CKeyLogTab CParentTabPage phím

giao diện dùng để cho

người dùng nhập các

phím cần khóa 9 CLockKeyAddDlg CParentTabPage

giao diện dùng để

người quản lý gởi tin

nhắn đến một máy 10 CMessageTab CParentTabPage

35

hay nhiều máy

giao diện dùng để

11 CScrCapTab CParentTabPage chụp màn hình

giao diện dùng để

quản lý các ứng dụng

phía máy khách 12 CApplistTab CParentTabPage

giao diện dùng để

quản lý phục vụ các

dịch vụ như món ăn,

thức uống cho khách

hàng 13 CServiceTab CParentTabPage

nhập dữ liệu về trạng

thái hoạt động của

dịch vụ 14 CChgSrvStartupDlg CDialog

nhập dữ liệu về trạng

thái khởi động của

dịch vụ 15 CChgSrvStatusDlg CDialog

giao diện dùng để

quản lý các service

phía máy khách 16 CSrvListTab CParentTabPage

dùng để chứa các

giao diện quản trị 17 CAdminTab CParentTabPage

dùng để quản lý việc

tính cước, giá cả các

dịch vụ kèm theo 18 CWorkStationTab CParentTabPage

dùng quản lý chương

trình sau khi có một

client bị đứt kế nối 19 CAfterCrashDlg CDialog

20 CBannerDlg CDialog giao diện dùng nhập

36

banner, rồi xuất các

quy định ở máy khách

giao diện dùng nhập

các thông tin về

Server lúc bắt đầu 21 CInfoServerDlg CDialog

giao diện dùng quản lý

loại thức ăn, nước

uống 22 CInputCategoryDlg CDialog

giao diện dùng quản lý

các món ăn, thức

uống 23 CInputDishDlg CDialog

giao diện dùng quản lý

24 CInputMemberDlg CDialog thanh viên tham gia

giao diện dùng quản lý

25 CDebitDlg CDialog các khách hàng nợ

giao diện dùng quản lý

giá cả các ngày 26 CInputPriceDlg CDialog

giao diện dùng nhập

27 CInputValueDlg CDialog giá cả của ngày

giao diện dùng thống

kê các đăng nhập sử

dụng của khách hàng 28 CDailyReportDlg CDialog

giao diện dùng thống

kê số tiền máy khách

kiếm được trong một

tháng 29 CMonthReport CDialog

giao diện dùng thống

30 CDebitReportDlg CDialog kê các khách hàng nợ

31 CdebitDetail- CDialog giao diện dùng xuất

37

ReportDlg chi tiết về một khách

hàng nợ

giao diện chương

trình Server 32 CCafeServerDlg CDialog

2.2.3.2

Xử lý Server:

CInputPriceDay

CSolveMember

CInputDish

CSolveCategory

CInputCategory

CSolveDish

CSolveDailyReport

CSolveLogin

CCafeDB

CSolveMonthReport

CSolveFee

CSolveDebitList

CSolveTableFee

CSolveDebitDetail

CSolveFeeDay

CADODatabase

CADORecordSet

CADOCommand

CADOFieldInfo

CADOParameter

CADOException

Hình 2-8 Thiết kế lớp xử lý Server

38

STT Tên lớp Kế thừa từ lớp Chức năng

Lớp xử lý việc quản

1 CSolveMember CCafeDB lý các thành viên

Lớp xử lý việc quản

lý các loại món ăn,

thức uống 2 CSolveCategory CCafeDB

Lớp xử lý việc quản

lý các món ăn, thức

uống 3 CSolveDish CCafeDB

Lớp xử lý việc quản

lý Login,Logout 4 CSolveLogin CCafeDB

Lớp xử lý việc tính

5 CSolveFee CCafeDB tiền

Lớp xử lý việc quản

6 CSolveTableFee CCafeDB lý tiền phí

Lớp xử lý việc quản

7 CSolveFeeDay CCafeDB lý tiền phí

Lớp xử lý việc quản

lý giá cả 8 CInputPriceDay CCafeDB

Lớp xử lý việc quản

9 CInputDish CCafeDB lý món ăn,thức uống

Lớp xử lý việc quản

10 CInputCategory CCafeDB lý loại món ăn

Lớp xử lý việc báo

11 CSolveDailyReport CCafeDB cáo hàng ngày

Lớp xử lý việc báo

12 CSolveMonthReport CCafeDB cáo theo tháng

13 CSolveDebitList CCafeDB Lớp xử lý việc nợ

39

của các thành viên

Lớp xử lý việc nợ

của các thành viên

một cách chi tiết 14 CSolveDebitDetail CCafeDB

15 CADODatabase CADOCommand

16 CADORecordset CADOCommand, CADOFieldInfo

17 CADOCommand CADOParameter

18 CADOFieldInfo

19 CADOParameter

20 CADOException

2.2.4 Thiết kế lớp trên Client:

2.2.4.1

Screen:

CBlockingSocketException

CSockAddr

CBlockingSocket

CInfoPcDlg

CScreenDlg

CLogonDlg

Hình 2-9 Thiết kế lớp Screen

Kế thừa từ

STT Tên lớp lớp Chức năng

Chỉ địa chỉ IP, thông tin Port

1 CSockAddr sockaddr_in dịch vụ

40

Nó thay thế lớp Socket của

MFC. Đây là lớp giữ chức

năng quan trọng nhất trong

chương trình vì nó có thể

thiết lập, tiếp nhận kết nối và

quản lý việc truyền dữ liệu. 2 CBlockingSocket CObject

Lớp quản lý lỗi cho việc thiết

lập, tiếp nhận kết nối và quản CblockingSocket-

lý việc truyền dữ liệu. 3 Exception CException

Dùng để nhập thông tin khi

không có thông tin kết nối 4 CInfoPcDlg

Dùng để nhập thông tin

Logon 5 CLogonDlg

Giao diện che màn hình

không cho khách hàng sử

dụng máy khách 6 CScreenDlg

2.2.4.2

Client:

CCafeClientDlg

COrder

CKeyLogClient

CKeyLockCLient

CTaskMgr

CShutdownClient

CKeyClient

CSockAddr

CBlockingSoket

CBlockingSocketException

Hình 2-10 Thiết kế lớp Client

41

Kế thừa từ

STT Tên lớp lớp Chức năng

Chỉ địa chỉ IP, thông tin

Port dịch vụ 1 CSockAddr sockaddr_in

Nó thay thế lớp Socket

của MFC. Đây là lớp giữ

chức năng quan trọng

nhất trong chương trình vì

nó có thể thiết lập, tiếp

nhận kết nối và quản lý

việc truyền dữ liệu. 2 CBlockingSocket CObject

Lớp quản lý lỗi cho việc

thiết lập, tiếp nhận kết nối

và quản lý việc truyền dữ CblockingSocket-

liệu. 3 Exception CException

Lớp quản lý lỗi cho việc

4 CKeyClient Lock hay Log key

Giao diện phục vụ việc

đặt món ăn của khách

hàng 5 COrder CDialog

6 CKeyLockClient CKeyClient Lớp xử lý khóa phím

Lớp xử lý ghi nhận phím

7 CKeyLogClient CKeyClient sử dụng

Giao diện chính của

8 CCafeClientDlg chương trình Client

42

2.2.5 Hiện thực hóa Use Case:

2.2.5.1

Use case Start Server:

: User

Object1 : CCafeServerDlg

Object2 : CBlockingSocket

1: StartServer( )

2: CreateConnection( )

3: StartListenConnection( )

Hình 2-11 Sequence Diagram Start Server

43

2.2.5.2

Use case Login:

l

g D t n e

i l

C e f a C C

j

: 7 t c e b O

) ( t c e n n o C

: 8

: ) t n e

i l

t e k c o S g n

i

l

l

j

C ( 6 t c e b O

k c o B C

l

l

l

u f s s e c c u S e s o C

) ( e s o C

:

7

g D n e e r c S C

:

5

j

) ( n o i t a c

i l

t c e b O

t

) ( e g a s s e M d n e S

l

:

p p A e s o C

9

: 5

e k c o S g n

i

: ) n e e r c S ( 4

j

l

k c o B C

) ( n o

t c e b O C

t

) ( e g a s s e M d n e S

) ( e g a s s e M d n e S

t

: 4

: 6

e k c o S g n

i

: ) r e v r e S ( 3

i t c e n n o C p e c c A

:

l

j

0 1

k c o B C

t c e b O

i

l

n g o L e v o S C

:

2

) ( o f n I t e S

j

: 3

t c e b O

) ( e s a b a t a D k c e h C

b a T n o i t a t

: 2

S k r o W C

j

: 1 t c e b O

i

) ( r e t u p m o C n g o L : 1

r e s U

:

Hình 2-12 Sequence Diagram Login

44

2.2.5.3

Use case Logout:

l

) ( n o

t

g D n e

i l

C e

f

l

a C C

i t c e n n o C e s o C

:

:

) ( n o

8

8

t c e

j

b O

t

: ) t

l

i t c e n n o C e s o C

n e

:

i l

7

) ( n e e r c S

t r a t

e k c o S g n ki c o

C ( 7 t c e

l

j

S

B C

: 9

b O

l

g D n e e r c S C

) ( n o

: 6 t c e

j

b O

i t c e n n o C

) ( e g a s s e M d n e S

t

:

t r a S

6

:

0 1

: ) n e e r c S

t e k c o S g n ki c o

l

( 5 t c e

j

B C

b O

) ( n o

) ( e g a s s e M d n e S

: 1 1

: ) r e v r e S

i t c e n n o C t p e c c A

t e k c o S g n ki c o

( 4 t c e

l

j

: 2 1

B C

b O

t r o p e R y

l i

: 3 t c e

j

a D e v

b O

l

) ( o

f

n

I t

o S C

n e

i l

n

i

o f n I t n e

i l

C e v a S

:

g o L e v

l

3

C e t e

l

o S C

) ( r e t u p m o C t u o g o L : 5

e D

: 4

) ( n

i

: 2 t c e

j

b O

g o L o

f

n

I

e

t

e

l

b a T n o

e D

: 2

i t a t S k r o W C

: 1 t c e

j

b O

r e s U

) ( r e t u p m o C t u o g o L : 1

:

Hình 2-13 Sequence Diagram Logout

45

2.2.5.4

Use case Paid

: ) r e v r e S

i

( 7 t c e

l

j

t e k c o S g n k c o B C

b O

e e F e

l

: 6 t c e

j

b a T e v

l

b O

o S C

) ( e

l

b a T

t

e G

:

5

y a D e e F e v

l

o S C

) ( y a D t e S

: 4

: 5 t c e

j

b O

) ( e c

i r

P

t e G

: 6

) ( e e F e

t

e e F e v

l

o S C

u p m o C

:

7

: 4 t c e

j

) ( r e t u p m o C

b O

t u o g o L : 2 1

t r o p e R y

l i

) ( e e F

: 3 t c e

j

t e G

a D e v

b O

l

: 8

) ( e e F r e t u p m o C

o S C

: 3

) ( o f n I t n e

i l

n

C e v a S

i

: 9

) ( o f n I t n e

i l

g o L e v

l

C e t e

l

o S C

e D

: 1 1

: 2 t c e

j

b O

) ( e e F

: 0 1

) ( e e F r e t u p m o C

: 2

b a T n o

i t a t S k r o W C

) ( r e

t

: 1 t c e

j

b O

u p m o C d

i

a P

:

1

r e s U

:

Hình 2-14 Sequence Diagram Paid

46

2.2.5.5

Use Case SetBanner:

Object2 : CCafeClientDlg

: User Object1 : CCafeServerDlg Object2(Server) : CBlockingSocket

Object3(Client) : CBlockingSocket

1: EnterBanner( )

2: SetBanner( )

3: SendMessage( )

4: GetBanner( )

5: ShowBanner( )

Hình 2-15 Sequence Diagram SetBanner

2.2.5.6

Use Case Service Order

: User

Object1 : CServiceTab Object2 : CMyHFlexGrid

Object2 : CWorkStationTab

Object3 : CSolveLoginService

1: ServeDish( )

2: ShowInfo( )

3: UpdateServiceFee( )

4: SaveToDatabase( )

Hình 2-16 Sequence Diagram Service Order

2.2.5.7

Use case Daily Report

47

: User

Object1 : CDailyReportDlg

Object2 : CDailyReportFlexGrid

Object3 : CSolveDailyReport

1: DailyReport( )

2: OpenDatabase( )

3: GetAllInfo( )

4: ShowReport( )

Hình 2-17 Sequence Diagram Daily Report

48

2.2.5.8

Use case Debit Report:

t r o p e R

l i

a t e D

j

: 6 t c e b O

l

t i b e D e v o S C

) ( o f n I l l

d i r

A t e G

) ( l i

t

l

: 8

:

5

a e D w o h S

G x e F t r o p e R

j

l i

:

9

t

t c e b O

a e D

t i

) ( e s a b a t a d n e p O

: 7

b e D C

l

g D

t r o p e R

l i

a t e D

t i b e D C

j

: 4 t c e b O

f

i

) ( o n

j

t

l

: 3 t c e b O

I t r o p e R e S

:

t s L t i b e D e v o S C

6

f

) ( o n

I l l

d i r

t

A e G

l

:

) 3

G x e F t r o p e R

) ( t r o p e R w o h S

: 4

t i b e D C

( e s a b a t a D n e p O

: 2

j

: 2 t c e b O

l

) ( l i

g D

a t e D

t r o p e R

t i

t r o p e R

: 5

b e D C

:

1

j

) ( t r o p e R

t c e b O

t i b e D

: 1

r e s U

:

Hình 2-18 Sequence Diagram Debit Report

49

2.2.5.9

Use case Month Report

: User

Object1 : CMonthReportDlg

Object2 : CMSFlexGrid

Object3 : CSolveMonthReport

1: MonthReport( )

2: OpenDatabase( )

3: GetAllInfo( )

4: ShowReport( )

Hình 2-19 Sequence Diagram Month Report

2.2.5.10 Use case Manage Cafeteria:

Object3 : CInputCategory

: User

Object1 : CInputCategoryDlg

Object2 : CCategoryListFlexGrid

1: Category( )

2: OpenDatabase( )

3: GetAllInfo( )

4: ShowCategory( )

2.2.5.10.1 Show:

Hình 2-20 Sequence Diagram Manage Cafeteria Show

50

: User

Object1 : CInputCategoryDlg Object3 : CInputCategory

Add new Category

1: EnterNewInfo( )

2: Add( )

3: SetInfo( )

4: Save( )

2.2.5.10.2 Add:

Hình 2-21 Sequence Diagram Manage Cafeteria Add

Object1 : CInputCategoryDlg

Object2 : CCategoryListFlexGrid Object3 : CInputCategory

: User

1: ChooseCategory( )

2: Edit( )

3: UpdateInfo( )

4: Update( )

2.2.5.10.3 Edit

Hình 2-22 Sequence Diagram Manage Cafeteria Edit

51

Object3 : CInputCategory

Object2 : CCategoryListFlexGrid

: User

Object1 : CInputCategoryDlg

1: ChooseCategory( )

2: Delete( )

3: DeleteCategory( )

4: Delete( )

2.2.5.10.4 Delete:

Hình 2-23 Sequence Diagram Manage Cafeteria Delete

2.2.5.11 Use case Manage Debit

2.2.5.11.1 Add

52

l i

a t e D

t i

) ( e v a s : 9

: 5 t c e

j

b e D e v

b O

l

o S C

t s

i

L t i

) ( e v a S

: 6

: 4 t c e

j

b e D e v

l

b O

o S C

t r o p e R y

l i

: 3 t c e

) ( o f n I l i

j

a D e v

b O

l

o S C

a t e D t e S

l

i

: 8

g D

t i

) ( o f n I c s a B

t e S

b e D C

) ( o f n I l i

: 5

: 2 t c e

j

) (

b O

a t e D t e G

: 7

) ( o f n I n o s r e P

l

l l

n o s r e P

g D

A

m r o F n e p O

t i

: 2

t e G

) ( o

f

b e D

w e n d d A

: 4

n I r e

t

n E

r e v r e S e f a C C

:

3

: 1 t c e

j

) ( t i

b O

b e D

: 1

r e s U

:

Hình 2-24 Sequence Diagram Debit Add

53

l i

a t e D

) ( e v a s : 2 1

j

l

: 5 t c e b O

t i b e D e v o S C

i

) ( e v a S

l

: 0 1

t s L t i b e D e v o S C

) ( o f n I l i

) ( o f n I l i

) ( o f n I l i

j

a t

: 4 t c e b O

t

a t e D t e S

e D t e S

a t e D e G

:

: 5

6

: 1 1

) ( o f n I c

) ( o f n I c

) ( o f n I c

i

i

i

t r o p e R y

l i

j

s a B t e S

s a B t e S

s a B t e G

l

: 3 t c e b O

: 9

: 3

: 4

a D e v o S C

l

g D

) ( o f n I w o h S

t i b e D C

: 7

j

: 2 t c e b O

l

) ( o f n I c

i

) ( t i

d E

:

g D r e v r e S e f a C C

8

s a B r e t n E

:

j

: 1 t c e b O

) 2 ( t i b e D

: 1

r e s U

:

Hình 2-25 Sequence Diagram Manage Debit Edit

54

2.2.5.12 Use case Manage Kind of Food:

: User Object1 : CInputDishDlg Object2 : CDishListFlexGrid Object3 : CInputDish

1: Dish( )

2: OpenDatabase( )

3: GetAllInfo( )

4: ShowDish( )

Add new Dish

5: EnterNewInfo( )

6: Add( )

7: SetInfo( )

8: Save( )

2.2.5.12.1 Add

Hình 2-26 Sequence Diagram Manage Kind of Food Add

2.2.5.12.2 Edit

55

: User Object1 : CInputDishDlg Object2 : CDishListFlexGrid Object3 : CInputDish

1: Dish( )

2: OpenDatabase( )

3: GetAllInfo( )

4: ShowDish( )

5: ChooseDish( )

6: Edit( )

7: UpdateInfo( )

8: Update( )

Hình 2-27 Sequence Diagram Manage Kind of Food Edit

2.2.5.12.3 Delete

56

: User Object1 : CInputDishDlg Object2 : CDishListFlexGrid Object3 : CInputDish

1: Dish( )

2: OpenDatabase( )

3: GetAllInfo( )

4: ShowDish( )

5: ChooseDish( )

6: Delete( )

7: DeleteDish( )

8: Delete( )

Hình 2-28 Sequence Diagram Manage Kind of Food Delete

2.2.5.13 Use case Manage Member:

2.2.5.13.1 Add

57

: User

Object1 : CInputMemberDlg Object2 : CMemberFlexGridObject3 : CSolveMember

1: Member( )

2: OpenDatabase( )

3: GetInfo( )

4: ShowMember( )

Add Member

5: EnterInformation( )

6: Add( )

7: SetInfo( )

8: Save( )

Hình 2-29 Sequence Diagram Manage Member Add

2.2.5.13.2 Edit

58

: User

Object1 : CInputMemberDlg Object2 : CMemberFlexGridObject3 : CSolveMember

1: Member( )

2: OpenDatabase( )

3: GetInfo( )

4: ShowMember( )

Edit Member

5: ChooseMember( )

6: Edit( )

7: SetInfo( )

8: Update( )

Hình 2-30 Sequence Diagram Manage Member Edit

2.2.5.13.3 Delete

59

: User

Object1 : CInputMemberDlg Object2 : CMemberFlexGridObject3 : CSolveMember

1: Member( )

2: OpenDatabase( )

3: GetInfo( )

4: ShowMember( )

Delete Member

5: ChooseMember( )

6: Delete( )

7: SetInfo( )

8: Update( )

Hình 2-31 Sequence Diagram Manage Member Delete

60

2.2.5.14 Use case Manage Price Day:

: 6 t c e

j

l

b O

y a D e e F e v o S C

l

l

l

) ( y a D e e F t e S

: 7 1

j

l

l

: 5 t c e b O

) ( e b a T o f n I t e S

: 5

e b a T e e F e v o S C

) ( e b a T o f n I m o r F y a D e e F t e G

) ( y a D t e S

: 6

: 3

) ( e b a T o f n I t e G

: 4

y a D e c i r

j

: 4 t c e b O

P t u p n I C

y a D e c i r

P e u

l

) ( o f n I l l

l

a V t u p n I C

A t e G

: 7

) (

j

l

) ( e b a T o f n I t e S

: 3 t c e b O

t

: 6 1

) ( e u a V e G

m r o F n e p O

:

4 1

) ( e c i r

d i r

: 2 1

) ( e s a b a t a D n e p O

l

: 2

) ( y a D e c i r

G x e F

i

: 2 t c e

j

P w e N w o h S

P w o h S

:

b O

: 8

5 1

l

t s L y a D e c i r

) ( e u a V

P C

r e t n E

: 3 1

l

i

g D y a D e c i r

) ( o f n I w e N r e t n E

:

) ( e m T & y a D e s o o h C

1 1

P t u p n I C

: 9

y a D

f

) ( t i

j

d E

:

) ( y a D e c i r

: 1 t c e b O

O e c i r

P

0 1

P

: 1

t i

d E

r e s U

:

Hình 2-32 Sequence Diagram Manage Price Day

61

2.2.5.15 Use case Lock Key:

t

n e

i l

C k c o L y e K C

:

5

l

j

t c e b O

l

t

) ( y e K k c o L : 6

g D n e

i l

u f s s e c c u S k c o L

f

C e a C C

j

f

) ( o n

: 4 t c e b O

I t

) ( o f n I t e S

e G

:

: 7

5

: ) t n e

i l

i

l

j

C ( 3 t c e b O

t e k c o S g n k c o B C

) ( e g a s s e M d n e S

) ( e g a s s e M d n e S

: 8

: 4

t e k c o S g n

i

l

j

k c o B C

: ) r e v r e S ( 2 t c e b O

f

) ( o n

I t

l

e S

:

3

) ( e g a s s e M w o h S

: 9

g D r e v r e S e f a C C

j

) ( k c o L y e K

: 1 t c e b O

t

t r a S

:

2

) ( k c o L e d o M e h t e s o o h C

r e s U

: 1

:

Hình 2-33 Sequence Diagram Lock Key

62

2.2.5.16 Use case Log Key

t

n e

i l

C g o L y e K C

:

5

l

j

t c e b O

l

t

) ( y e K g o L : 5

g D n e

i l

u f s s e c c u S g o L

f

C e a C C

j

: 4 t c e b O

) ( o f n I t e S

) ( o f n I t e G

: 6

: 4

: ) t n e

i l

t e k c o S g n

i

l

j

C ( 3 t c e b O

k c o B C

) ( e g a s s e M d n e S

) ( e g a s s e M d n e S

:

: 7

3

t e k c o S g n

i

l

j

k c o B C

: ) r e v r e S ( 2 t c e b O

l

) ( o f n I t e S

: 2

) ( e g a s s e M w o h S

:

8

g D r e v r e S e f a C C

j

) ( g o L y e K

: 1 t c e b O

t

t r a S

:

1

r e s U

:

Hình 2-34 Sequence Diagram Log Key

63

2.2.5.17 Use case Message:

: User

Object : CMessageTab Object : CBlockingSocket Object : CBlockingSocket Object : CCafeClientDlg

1: ChooseComputer( )

2: EnterMesage( )

3: SetInfo( )

4: SendMessage( )

5: GetInfo( )

6: ShowMessage( )

Hình 2-35 Sequence Diagram Send Message

2.2.5.18 Use case Manage Remote Computer

: User

Object : CLoggingtab

Object : CCafeClientDlg Object : CShutDownClient

Object(Server) : CBlockingSocket

Object(Client) : CBlockingSocket

1: SetOption

2: Shutdown

3: SetInfo( )

4: SendMessage( )

5: GetInfo( )

6: Shutdown( )

7: Shutdown( )

Hình 2-36 Sequence Diagram Manage Remote Computer

64

2.2.5.19 Use case Manage Application:

Object4 : CCafeClientDlg Object5 : CTaskMgr

: User Object1 : CAppListtab Object2(Server) : CBlockingSocket

Object3(Client) : CBlockingSocket

1: SetComputer( )

2: ListAll( )

3: SetInfo( )

4: SendMessage( )

5: GetInfo( )

6: RequestList( )

7: GetWindowList( )

8: SetInfo( )

9: SendMessage( )

10: GetInfo( )

2.2.5.19.1 List:

Hình 2-37 Sequence Diagram Manage Application - List

2.2.5.19.2 Start:

65

) ( p p A

t

t r a S

r g M k s a T C

:

8

j

: 5 t c e b O

) ( p p A

l

t r a t

S

) ( t l u s e R t e G

g D t n e

: 7

: 9

i l

C e f a C C

f

j

) ( o n

I t

: 4 t c e b O

e S

) ( o f n I t e G

:

6

: 0 1

: ) t n e

i l

t e k c o S g n

i

j

l

C ( 3 t c e b O

k c o B C

) ( e g a s s e M d n e S

) ( e g a s s e M d n e S

: 5

: 1 1

t e k c o S g n

i

) ( t l

l

j

k c o B C

: ) r e v r e S ( 2 t c e b O

) ( o f n I t e S

u s e R w o h S

i

: 4

:

2 1

b a t t s L p p A C

j

) ( p p A

: 1 t c e b O

t r a t

) ( o f n I r e t n E

S

) ( r e t u p m o C t e S

: 3

: 2

: 1

r e s U

:

Hình 2-38 Sequence Diagram Manage Application - Start

66

Object4 : CCafeClientDlg Object5 : CTaskMgr

: User Object1 : CAppListtab Object2(Server) : CBlockingSocket

Object3(Client) : CBlockingSocket

1: SetComputer( )

2: ChooseApp( )

3: StopApp( )

4: SetInfo( )

5: SendMessage( )

6: GetInfo( )

7: StopApp( )

8: StopApp( )

9: GetResult( )

10: SetInfo( )

11: SendMessage( )

12: ShowResult( )

2.2.5.19.3 Stop:

Hình 2-39 Sequence Diagram Manage Application – Stop

2.2.5.20 Use case Manage Service:

2.2.5.20.1 Show List

67

Object7 : CTaskMgr

Object6 : CCafeClientDlg

: User

Object1 : CSrvListtab Object4(Server) : CBlockingSocket

Object5(Client) : CBlockingSocket

1: SetComputer( )

2: ListAll( )

3: SetInfo( )

4: SendMessage( )

5: GetInfo( )

6: RequestServiceList( )

7: GetServiceList( )

8: SetInfo( )

9: SendMessage( )

10: GetInfo( )

11: ShowList( )

Hình 2-40 Sequence Diagram Manage Service – Show List

68

) ( p u t r a

t

r g M k s a T C

S e g n a h C

:

9

j

) ( t l

: 7 t c e b O

) ( p u t r a t

t

l

u s e R e G

:

S e g n a h C

g D t n e

0 1

i l

: 8

C e f a C C

j

f

) ( o f n

: 6 t c e b O

I t e S

) ( o n I t e G

t

: 7

: 1 1

: ) t n e

i l

e k c o S g n

i

C ( 5

j

l

t c e b O

k c o B C

t

) ( e g a s s e M d n e S

) ( e g a s s e M d n e S

:

6

: 2 1

e k c o S g n

i

: ) r e v r e S ( 4

l

j

k c o B C

t c e b O

l

g D p u

t r a

t

S v r

f

) ( o n

I t

e S

S g h C C

:

) ( t l u s e R w o h S

:

5

2

: 3 1

j

l

t c e b O

) ( e

l

) ( e y t S t e G

: 4

b a

y t S p u t r a

i

t

t t s L v r S C

S e s o o h C

i

:

3

j

: 1 t c e b O

) ( r e t u p m o C t e S

) ( e c v r e S e s o o h C

: 1

: 2

r e s U

:

ChangeStartupService:

Hình 2-41 Sequence Diagram Manage Service – Change Startup Service

69

) ( s u t a t

r g M k s a T C

S e g n a h C

:

j

: 7 t c e b O

t

l

) ( t l u s e R e G

:

) 9 ( s u t a t S e g n a h C

g D t n e

0 1

i l

: 8

C e f a C C

j

f

: 6 t c e b O

) ( o n I t e S

) ( o f n I t e G

: 7

: 1 1

: ) t n e

i l

t e k c o S g n

i

l

j

C ( 5 t c e b O

k c o B C

) ( e g a s s e M d n e S

) ( e g a s s e M d n e S

:

: 6

2 1

t e k c o S g n

i

l

j

k c o B C

: ) r e v r e S ( 4 t c e b O

l

g D s u t a t S v r

S g h C C

) ( o f n I t e S

) ( t l u s e R w o h S

: 5

: 3 1

j

l

: 3 t c e b O

l

) ( e y t

) ( e y t S t e G

: 4

t

i

b a t t s L v r

S C

:

1

S s u a t S e s o o h C

i

t

: 3

j

t c e b O

t

) ( r e u p m o C e S

) ( e c v r e S e s o o h C

:

1

: 2

r e s U

:

Change Status

Hình 2-42 Sequence Diagram Manage Service – Change Status

70

2.2.6 Thiết kế cơ sở dữ liệu

Category

STT

Tên

Thuộc tính

Mô tả

1 MALOAI

Số nguyên

2 TENLOAI

Text

tên lọai thức ăn, nước uống

Hình 2-43 Cơ sở dữ liệu

DailyReport

STT

Tên

Thuộc tính

Mô tả

1 PC_NO

Text

Giờ lúc khách hàng bắt đầu

2 START_TIME Ngày giờ

sử dụng máy

Giờ lúc khách hàng kết thúc

sử dụng máy

3 END_TIME

Ngày giờ

4 USERNAME

Text

tiền khi khách hàng sử dụng

các dịch vụ có liên quan

5 ORDER_FEE số thực

6 WS_FEE

số thực

tiền phí sử dụng máy

7 TOTAL_FEE

số thực

tổng phí

8

ID_SERVICE Text

Bảng 2-1 Category

DEBIT_DETAIL

STT

Tên

Thuộc tính

Mô tả

Bảng 2-2 Daily Report

71

1 ID_DEBIT

số nguyên

2 PC_NO

Text

3 USERNAME

Text

Giờ lúc khách hàng bắt

4 START_TIME Ngày giờ

đầu sử dụng máy

Giờ lúc khách hàng kết

thúc sử dụng máy

5 END_TIME

Ngày giờ

6 TOTAL_FEE

số thực

tổng phí

DEBIT_LIST

STT

Tên

Thuộc tính

Mô tả

1 ID

số nguyên

2 NAME

Text

Tên khách nợ

3 ADDRESS

Text

4 PHONE

Text

5 TOTAL_FEE

số thực

Tổng tền phải trả

Tiền khách có thể trả

6 PREPAY

số thực

trước

Bảng 2-3 Bảng Debit_Detail

DISH

STT

Tên

Thuộc tính

Mô tả

1 MA

số nguyên

2 DESCRIPTION Text

Tên món thức ăn

Loại thức ăn, nước

3 MALOAI

số nguyên

uống

4 PRICE

số thực

giá cả

Bảng 2-4 Debit List

FEE_DAY

STT

Tên

Thuộc tính

Mô tả

1 ID_TABLE

Text

2 BEGIN_TIME Ngày giờ

giờ bắt đầu

3 END_TIME

Ngày giờ

giờ kết thúc

4 FEE_HOUR

số thực

Bảng 2-5 Dish

Bảng 2-6 Fee-Day

72

LOGIN

STT

Tên

Thuộc tính

Mô tả

1 PC_NO

Text

2 USERNAME

Text

3 PASSWORD Text

4 START_TIME Ngày giờ

5 END_TIME

Ngày giờ

6 FEE

số thực

7 ID_SERVICE Text

LOGIN_SERVICE STT

Tên

Thuộc tính

Mô tả

1 ID

Text

2 MA_DISH

số nguyên

3 AMOUNT

số nguyên

Bảng 2-7 Login

MEMBER

STT

Tên

Thuộc tính

Mô tả

1 USERNAME Text

2 PASSWORD Text

3 ADDRESS

Text

4 TELEPHONE Text

5 FEE

số thực

6 PRIORITY

số nguyên

Bảng 2-8 Login Service

MONTH_REPORT

STT

Tên

Thuộc tính

Mô tả

1 DATE

Ngày giờ

2 PC_NO

Text

3 TOTAL_FEE

số thực

Bảng 2-9 Member

TABLE_DAY

STT

Tên

Thuộc tính

Mô tả

1 ID_TABLE

Text

2 DAY

Ngày giờ

Bảng 2-10 Month Report

Bảng 2-11 Table Day

73

2.2.7 Thiết kế màn hình :

2.2.7.1

Thiết kế màn hình trên Client:

2.2.7.1.1 Màn hình Screen:

Hình 2-44 Màn hình Screen

2.2.7.1.2 Màn hình Chính Client

74

Hình 2-45 Màn hình chính Client

Hình 2-46 Màn hình Order phí Client

2.2.7.2

Thiết kế màn hình trên Server:

2.2.7.2.1 Tab WorkStation:

75

Hình 2-47 Màn hình Server – WorkStation

2.2.7.2.2 Tab Service:

76

Hình 2-48 Màn hình Server – Service

2.2.7.2.3 Tab Administration:

Hình 2-49 Màn hình Server – Keylock

77

Hình 2-50 Màn hình Server – Keylog

Hình 2-51 Màn hình Server – Message

78

Hình 2-52 Màn hình Server – Apllication

Hình 2-53 Màn hình Server – Service

79

Hình 2-54 Màn hình Server – Snapshot

2.3 Cài đặt và thử nghiệm:

2.3.1 Cài đặt:

Ứng dụng Server và CafeClient được phát triển sử dụng các công cụ và môi

trường sau:

+ Công cụ phân tích và thiết kế: Rational Rose 2003

+ Môi trường cài đặt ứng dụng: Windows XP Professional

+ Môi trường lập trình: Microsoft Visual Studio 6.0

2.3.2 Thử nghiệm:

Chương trình được cài đặt thử nghiệm trên phòng máy của trung tâm mạng

STT Tính năng thử nghiệm

1 Kết nối

Đánh giá Tốt

Tính cước và các dịch vụ liên quan

2 3 Quản trị từ xa 4 Chụp màn hình tĩnh 5 Chụp màn hình động

6 Policy

Tốt Tốt Tốt Tốt Tùy thuộc vào thiết lập máy phía Client

Máy Tính Nhất Nghệ - đường Bà Huyện Thanh Quan - với kết quả như sau:.

80

Chương 3 Các kỹ thuật lập trình

3.1 Kỹ thuật lập trình sự kiện và hook

Trong quá trình thực hiện phần mềm, có một yêu cầu quản trị hệ thống là

người quản trị cần biết lúc này người dùng đang gõ nội dung gì trên bàn phím hoặc

anh ta có nhu cầu khóa tạm thời bàn phím hay một số phím nhất định. Các nhu cầu

đó dẫn đến tình huống cần một cơ chế quản lý và kiểm soát bàn phím. Trong hệ

thống Windows, có một cơ chế đáp ứng như thế : cơ chế hook.

3.1.1 Sự kiện và thông điệp trên HĐH Windows

Trước hết, ta phải hiểu thêm về cơ chế thông điệp của hệ điều hành

Windows. Đây là cơ chế cho phép các ứng dụng phân loại, lưu trữ, đáp lại tương tác

với người dùng cũng như là tương tác lẫn nhau.

* Hàng đợi thông điệp :

Để lưu trữ, phân loại, tương tác… Hệ điều hành Windows xây dựng hàng

đợi thông điệp. Hai loại hàng đợi thông điệp dùng cho mục đích này là:

o Hàng đợi hệ thống (System queue).

o Hàng đợi ứng dụng (Application queue).

Windows có các trình điều khiển thiết bị (Drivers) chịu trách nhiệm cho các

dịch vụ ngắt từ thiết bị phần cứng mouse và keyboard. Tại mỗi thời điểm ngắt phát

sinh, các Driver này gọi một điểm vào (hàm) đặc biệt trong USER.EXE để chỉ ra

rằng một sự kiện vừa xảy ra. Các sự kiện mouse, bàn phím khi xảy ra đều trước hết

được lưu vào hàng đợi hệ thống. Mọi tiến trình trong hệ thống đều chia sẻ hàng đợi.

Hàng đợi hệ thống chỉ làm một nhiệm vụ duy nhất là ghi nhận các sự kiện mouse,

bàn phím (nhấn, rê mouse, nhấn bàn phím…) khi có.

81

Hình 3-1 Hàng đợi ứng dụng

Khi một tiến trình được khởi tạo, một hàng đợi đại diện cho nó được tạo ra,

hàng đợi này (đôi khi được gọi là hàng đợi tác vụ) được dùng để chứa những thông

điệp sẽ được gởi cho các cửa sổ của ứng dụng. Những thông điệp này là những

thông điệp được gởi một cách tường minh bằng một trong hai hàm sau :

o PostMessage

o PostAppMessage

Ứng dụng có thể dùng hai hàm là GetMessage và PeekMessage do

Windows cung cấp để khảo sát hàng đợi của mình. Hai hàm này cho phép ứng dụng

lấy một thông điệp ra khỏi hàng đợi để từ đó phân loại và có những hồi đáp thích

hợp với người dùng.

3.1.2 Hook là gì ?

Hook là một cơ chế xử lý thông điệp của hệ thống mà một ứng dụng có thể

cài đặt một đoạn lệnh (subroutine) để theo lưu thông thông điệp trên hệ thống và xử

lý một số dạng thông điệp nào đó trước khi các thông điệp đến được thủ tục ở cửa

sổ đích.

3.1.3 Đặc tính của hook:

Hook có xu hướng làm chậm hệ thống vì chúng gia tăng số lượng công việc

xử lý của hệ thống cho mỗi thông điệp. Chỉ nên cài đặt hook khi cần thiết, và tháo

bỏ ngay khi không dùng nữa.

82

3.1.4 Các khái niệm trong hook:

3.1.4.1 Hook chains:

Hệ thống hỗ trợ nhiều loại hook; mỗi dạng cung cấp khả năng truy cập đến

khía cạnh khác nhau của cơ chế xử lý thông điệp. Chẳng hạn, ứng dụng có thể dùng

WM_MOUSE hook để kiểm soát lưu thông thông điệp của các thông điệp về

mouse.

Hệ thống duy trì một hook chain (dãy các hook) riêng rẽ cho mỗi loại hook.

Một hook chain là một danh sách các con trỏ trỏ đến các hàm do ứng dụng định

nghĩa, đặc biệt riêng gọi là các hook procedure (thủ tục hook). Khi một thông điệp

phát sinh mà liên quan đến một loại hook, hệ thống chuyền thông điệp cho mỗi

hook procedure tham chiếu từ hook chain, hết cái này đến cái khác. Hoạt động một

hook procedure thực hiện tùy thuộc vào loại hook quy định. Các hook procedure

cho một số loại hook chỉ có thể quan sát các thông điệp; số còn lại có thể chỉnh sửa

thông điệp hay chặn quá trình chuyền thông điệp trong hook chain, ngăn thông điệp

đến được hook procedure kế tiếp hoặc cửa sổ đích.

3.1.4.2 Hook procedure

Để tận dụng khả năng của mỗi loại hook, hệ thống cung cấp một hook

procedure và sử dụng hàm SetWindowsHookEx để cài đặt hook procedure vào

trong hook chain liên quan. Hook procedure phải theo công thức:

LRESULT CALLBACK HookProc(

int nCode,

WPARAM wParam,

LPARAM lParam

);

Có thể đặt tên tùy ý, không cần phải đúng là HookProc cho hook procedure.

Tham số nCode là mã hook mà hook procedure dùng để quyết định thao tác

thực hiện. Giá trị mã hook tùy thuộc vào loại hook; mỗi loại lại có bộ mã hook

mang tính chất riêng của nó. Các giá trị của tham số wParam và lParam tùy thuộc

83

mã hook, nhưng chúng đặc biệt chứa thông tin về thông điệp được gởi hay chuyển

(post).

Hàm SetWindowsHookEx luôn cài đặt một hook procedure ở đầu hook

chain. Khi một sự kiện xảy ra mà được quan sát bởi một loại hook, hệ thống sẽ gọi

thủ tục ở đầu hook chain liên quan đến hook. Mỗi hook procedure trong chain quyết

định có nên chuyển sự kiện sang thủ tục kế tiếp. Một hook procedure chuyển sự

kiện sang thủ tục kế bằng cách gọi CallNextHookEx.

Chú ý các hook procedure cho một số loại hook chỉ có thể quan sát thông

điệp mà thôi. Hệ thống chuyển thông điệp cho mỗi hook procedure, mặc cho mỗi

thủ tục có gọi CallNextHookEx.

Một hook toàn cục (global hook) kiểm soát các thông điệp cho mọi tiểu trình

trên cùng desktop với tiểu trình gọi hook. Một hook riêng cho tiểu trình (thread-

specific hook) kiểm sóat các thông điệp cho chỉ riêng tiểu trình đó thôi. Một hook

procedure toàn cục có thể được gọi trong ngữ cảnh của bất kỳ ứng dụng trên cùng

desktop với tiểu trình gọi, vì vậy thủ tục được gọi phải ở trong một module thư mục

liên kết động (dynamic linked library DLL) riêng rẽ. Một hook procedure riêng cho

tiểu trình chỉ được gọi trong ngữ cảnh của tiểu trình liên quan thôi. Nếu ứng dụng

cài đặt hook procedure một trong những tiểu trình của nó, hook procedure có thể

trong cùng module với phần mã còn lại của ứng dụng hay trong một DLL. Nếu một

ứng dụng cài đặt hook procedure cho một tiểu trình của một ứng dụng khác, thủ tục

phải ở trong DLL.

3.1.4.3 Các loại hook

Mỗi loại hook cho phép ứng dụng quan sát các khía cạnh khác nhau của cơ

• WH_CALLWNDPROC và WH_CALLWNDPROCRET Hooks

• WH_CBT Hook

• WH_DEBUG Hook

• WH_FOREGROUNDIDLE Hook

chế xử lý thông điệp của hệ thống. Các loại hook khả dụng là :

84

• WH_GETMESSAGE Hook

• WH_JOURNALPLAYBACK Hook

• WH_JOURNALRECORD Hook

• WH_KEYBOARD_LL Hook

• WH_KEYBOARD Hook

• WH_MOUSE_LL Hook

• WH_MOUSE Hook

• WH_MSGFILTER và WH_SYSMSGFILTER Hooks

• WH_SHELL Hook

Trong các hook kể trên, ta chỉ cần chú ý ba hook dành cho xử lý sự kiện bàn

phím WH_GETMESSAGE, WH_KEYBOARD, WH_KEYBOARD_LL.

3.1.4.3.1 WH_GETMESSAGE Hook

Hook cho phép quan sát các thông điệp sẽ trả về bởi các hàm GetMessage và

PeekMessage, có thể dùng hook để quan sát các dữ liệu nhập từ mouse và bàn phím

và các loại thông điệp khác từ hàng đợi thông điệp.

3.1.4.3.2 WH_KEYBOARD_LL Hook

Cho phép kiểm soát các sự kiện nhập từ bàn phím sẽ được chuyển đi trong

hàng đợi thông điệp.

3.1.4.3.3 WH_KEYBOARD Hook

Cho phép kiểm soát dòng lưu thông các thông điệp WM_KEYDOWN,

WM_KEYUP sẽ trả bởi hàm GetMessage hay PeekMessage. Hook cũng có thể

được dùng để kiểm soát các sự kiện nhập từ bàn phím sẽ được chuyển đi trong hàng

đợi thông điệp.

3.1.5 Tiếp cận vấn đề:

Như vậy, ta phải tạo một hook có khả năng chặn bắt các sự kiện bàn phím,

ghi nhận, cho phép hoặc hủy bỏ trước khi các thông điệp bàn phím đến được cửa sổ

85

đích. Trong các loại hook nêu trên, ta thấy các loại hook phù hợp là:

WH_GETMESSAGE, WH_KEYBOARD, WH_KEYBOARD_LL. Tuy nhiên, mục

tiêu đề ra là làm thế nào để kiểm soát bàn phím mà thôi, WH_GETMESSAGE kiểm

soát hết các thông điệp, đồng thời hạn chế lớn nhất là WH_GETMESSAGE không

có tính năng lọc bỏ thông điệp. Như vậy, ta chọn được hai hook WH_KEYBOARD,

WH_KEYBOARD_LL. Ta chọn WH_KEYBOARD vì dễ cài đặt hơn, tương thích với

nhiều phiên bản hệ điều hành Windows. Do chức năng khóa bàn phím là chức năng

có nhiều kỹ thuật khá thú vị, nên quá trình cài đặt chức năng này sẽ được đề cập

trước.

3.1.5.1 Tinh chế 0:

Xây d(cid:127)ng m(cid:127)t (cid:127)ng d(cid:127)ng (cid:127)(cid:127)n gi(cid:127)n cài (cid:127)(cid:127)t m(cid:127)t hook toàn c(cid:127)c. Khi (cid:127)ng d(cid:127)ng ch(cid:127)y, phím ‘e’ trên bàn phím s(cid:127) b(cid:127) vô hi(cid:127)u hóa (không gõ (cid:127)(cid:127)(cid:127)c n(cid:127)a).

Cài đặt hook toàn cục, ta cần viết các hàm cài đặt, gở bỏ hook và hook

procedure trong một module riêng, gọi là DLL (thư viện liên kết động). Trước hết,

ta cần khảo sát các hàm cài đặt, gở bỏ hook do Windows cung cấp. Các hàM API

này được nêu rõ trong Phụ lục Các hàm API hữu ích sử dụng trong chương

trình gồm: SetWindowsHookEx (cài đặt hook), UnhookWindowsHookEx (gở bỏ

hook), CallNextHookEx (truyền cho hook kế). Các hàm API của Windows từ đây

trở đi khi được đề cập đến nếu được sử dụng nhiều trong chương trình, sẽ được nêu

rõ trong Phụ lục Các hàm API hữu ích sử dụng trong chương trình.

Xây dựng hook procedure:

Đây là lúc thích hợp để đề cập việc xây dựng hàm quan trọng nhất, hook

procedure. Hook procedure là một callback function, tức là một hàm chỉ được gọi

bởi Windows mỗi khi có sự kiện ứng với hàm xảy ra

Các hook procedure đều có dạng sau:

LRESULT CALLBACK HookProc(

int nCode,

WPARAM wParam,

86

LPARAM lParam

);

Ta cần sử dụng WH_KEYBOARD nên ta sẽ khảo sát cụ thể hook

procedure cho WH_KEYBOARD:

LRESULT CALLBACK KeyboardProc(

int code,

WPARAM wParam,

LPARAM lParam

);

code : xác định cách thức hook procedure xử lý thông điệp, nó là một trong

hai giá trị sau :

HC_ACTION : Thông điệp đã được lấy ra khỏi hàng đợi thông điệp.

wParam và lParam chứa thông tin về thông điệp mà hook procedure nhận được.

HC_NOREMOVE : wParam và lParam mang thông tin của thông điệp, và

thông điệp vẫn còn trong hàng đợi (ứng dụng gọi PeekMessage với tùy chọn

PM_NOREMOVE).

Nếu code âm, hook procedure phải chuyển thông điệp đi bằng cách gọi hàm

CallNextHookEx và trả về kết quả nhận được.

wParam : chứa mã phím ảo của phím được nhấn.

lParam : cho biết số lần lặp lại, mã quét, cờ mở rộng, mã ngữ cảnh, cờ trạng

thái trước của phím, và cờ chuyển trạng thái:

0-15 cho biết số lần lặp phím, là số lần nhấn phím được tính khi người

dùng giữ phím.

16-23 cho biết mã quét.

25-28 dành riêng.

29 cho biết mã ngữ cảnh. Giá trị 1 nếu phím ALT được nhấn, 0 nếu ALT

nhả

30 cho biết trạng thái phím trước đó. Giá trị 1 nếu phím được nhấn trước

khi thông điệp được gởi, 0 nếu ngược lại.

87

31 cho biết trạng thái chuyển đổi. 0 nếu phím đang nhấn, 1 nếu phím

được thả.

Tới đây, ta đã vượt qua một lượng lớn kiến thức khá thú vị về cơ chế hook.

Đã đến lúc làm một việc gì đó cụ thể, ta cài đặt bài tóan nêu ở Tinh chế 0:

Xây dựng các hàm cài đặt gở bỏ: quy tắc viết hàm theo module DLL, cách

nạp một DLL vào bộ nhớ và thực thi, xem chi trong phần mã nguồn chương trình. Ở

đây, ta chỉ đề cập đến cách hàm hoạt động mà thôi.

Hàm cài đặt:

LRESULT __declspec(dllexport) InstallKeyHook()

Cài đặt một WH_KEYBOARD để xử lý thông điệp bàn phím và trả về

handle hook cài đặt thành công hoặc lỗi nếu thất bại.

Hàm gở bỏ:

LRESULT __declspec(dllexport) UninstallKeyHook()

Gở bỏ WH_KEYBOARD hook đã cài đặt, trả về mã thông báo kết quả.

Hook procedure :

LRESULT CALLBACK KeyboardProc(INT nCode, WPARAM wParam,

LPARAM lParam)

Ta chỉ xử lý khi thông điệp được lấy ra khỏi hàng đợi và chỉ xử lý một thông

điệp WM_KEYDOWN mà thôi (khi lọc bỏ thông điệp WM_KEYDOWN thì thông

điệp WM_KEYUP sẽ không được phát sinh, xem chi tiết về thông điệp bàn phím

trong Phụ lục Sự kiện bàn phím). Hai thông điệp WM_SYSKEYDOWN và

WM_SYSKEYUP cũng tương tự như thế.

Thử nghiệm:

Chương trình chạy hoạt động tốt nhưng khi ta thay đổi nhỏ như sau: cố

truyền một biến cho DLL, biến này cho biết mã phím ảo của phím sẽ bị chặn, chẳng

hạn, ‘e’, và truyền cho DLL như sau:

SetX(‘e’); //SetX là hàm đặt biến trong DLL.

và trong DLL khai báo một biến toàn cục như sau:

WPARAM x;

88

thì chương trình sẽ mất tác dụng khi ứng dụng của ta mất focus (không phải

là cửa sổ đang kích họat). Điều này không chấp nhận được vì ứng dụng ta mong

muốn cần phải chặn bắt các sự kiện bàn phím khi người dùng đang sử dụng.

Hình 3-2 Tinh chế 0

3.1.5.2 Tinh chế 1:

Xây d(cid:127)ng m(cid:127)t (cid:127)ng d(cid:127)ng cài (cid:127)(cid:127)t m(cid:127)t hook toàn c(cid:127)c. Khi (cid:127)ng d(cid:127)ng ch(cid:127)y, tùy theo phím ng(cid:127)(cid:127)i dùng gõ vào mà (cid:127)ng d(cid:127)ng s(cid:127) khóa phím (cid:127)ó.

Để giải quyết vấn đề, ta cần phải tìm hiểu kỹ cơ chế hoạt động cũng như tải

nạp một module DLL vào bộ nhớ khi ứng dụng cần. Điều cốt lõi ta cần biết chính là

không gian địa chỉ. Khi một DLL toàn cục được thực thi, nó sẽ thực thi trong ngữ

cảnh của tiến trình mà có sự kiện nó cần hook đang xảy ra. Vì đây là một DLL, nó

sẽ có một bản sao riêng rẽ của những dữ liệu cần dùng của nó (trong trường hợp ta

khảo sát, đó là biến toàn cục x) cho mỗi tiến trình. Vì vậy, mỗi lần hook procedure

được gọi, DLL sẽ nạp vào không gian địa chỉ của tiến trình cần hook, và một loạt

các dữ liệu mà DLL dùng sẽ được khởi tạo mới (chẳng hạn các biến toàn cục khai

báo ở mức độ tập tin như biến x đã nêu trên). Vì vậy, ta phải làm một cách nào đó

mà các dữ liệu ta cần (biến x) có thể dùng cho mọi thể hiện của DLL. Điều này có

thể thực hiện được bằng cách sử dụng đọan không gian địa chỉ chia sẻ (shared

segment), xem thêm chi tiết về vấn đề này trong phần Phụ lục DLL – thư viện liên

kết động.

89

Khi đó, do các biến ta cần đều được đặt trong đoạn không gian địa chỉ chia

sẻ, các thể hiện của DLL được nạp trong mỗi tiến trình đều “hiểu” (đọc được giá trị

trong bản gốc DLL nạp do ứng dụng của ta đặt). Để khai báo một phân đoạn không

gian địa chỉ chia sẻ, ta làm như sau:

#pragma data_seg(“.VAN”)

//Các biến cần sử dụng chung

#pragma data_seg()

#pragma comment(linker, “/section:.VAN,rws”)

với “.VAN” là tên đặt gợi nhớ tùy ý cho phân đoạn (nhưng không được dài

hơn 8 ký tự). #pragma comment ở trên đặt thêm một tùy chọn biên dịch cho các tập

tin biên dịch .OBJ.

Đến đây, mọi việc lại trở nên quá dễ dàng với phân đọan chia sẻ ta vừa tạo

ra. Ta chỉ việc tạo ra 255 biến trạng thái (kể cả các ký tự điều khiển và mở rộng, có

thể có tới 256 ký tự). Các biến này lưu trữ trạng thái của phím như sau:

#define MAX_KEYS_LOCK 255

static BOOL g_bHook[MAX_KEYS_LOCK]

với FALSE cho biết phím chưa khóa

TRUE cho biết phím đã khóa

đặt mảng các biến vào trong phân đọan vừa tạo trên và chỉnh sửa lại hook

procedure KeyboardProc:

Thế là ta hoàn tất vấn đề chính. Việc còn lại chỉ đơn giản là thiết lập hàm ghi

giá trị biến trong DLL và gọi nó trong ứng dụng

Thử nghiệm tinh chế 1:

Chương trình hoạt động khá tốt nhưng ta vẫn chưa đề cập đến các phím chức

năng (ví tổ hợp Alt-Tab…). Thật vậy, chương trình hoàn toàn bất lực trước các

phím chức năng vì ta không thiết kế chức năng “nhập” các phím chức năng, mà cho

dù có, ta cũng không “bắt” được. Điều này không chấp nhận được vì ứng dụng ta

mong muốn cần phải chặn bắt các sự kiện bàn phím khi người dùng đang sử dụng.

90

Hình 3-3 Tinh chế 1

3.1.5.3 Tinh chế 2:

Xây d(cid:127)ng m(cid:127)t (cid:127)ng d(cid:127)ng cài (cid:127)(cid:127)t m(cid:127)t hook toàn c(cid:127)c. Khi (cid:127)ng d(cid:127)ng ch(cid:127)y, cho phép vô hi(cid:127)u hóa b(cid:127)t k(cid:127) phím nào trên bàn phím.

Để giải quyết vấn đề này, ta cần xem xét lại khả năng của hook

WH_KEYBOARD. Hook không có khả năng chặn bắt các tổ hợp phím như: Alt-

Tab… Vì vậy, ta đành phải sử dụng hook khả dĩ cuối cùng là hook

WH_KEYBOARD_LL. Tuy nhiên, hook là một hook mới có từ Windows

NT/2000/XP trở về sau. Đây là một hook rất mạnh nhưng cách dùng cũng như

tham số đầu vào khác rất nhiều so với WH_KEYBOARD. Do đó, ta phải tinh chỉnh

lại hook procedure nếu không muốn thay đổi toàn bộ cài đặt từ trước.

Khảo sát hook procedure của WH_KEYBOARD_LL :

LRESULT CALLBACK LowLevelKeyboardProc(

int nCode,

WPARAM wParam,

LPARAM lParam

);

Ý nghĩa tham số:

91

[in]

nCode: xác định cách thức xử lý thông điệp. Nếu nCode âm, phải chuyển

thông điệp sang hook procedure kế, và trả về kết quả nhận được, chỉ có thể là giá

trị:

HC_ACTION wParam và lParam chứa thông tin về thông điệp bàn phím.

wParam: xác định loại thông điệp. Đó là: WM_KEYDOWN, WM_KEYUP,

WM_SYSKEYDOWN, và WM_SYSKEYUP.

lParam: trỏ đến cấu trúc KBDLLHOOKSTRUCT.

Cấu trúc KBDLLHOOKSTRUCT như sau:

typedef struct {

DWORD vkCode;

DWORD scanCode;

DWORD flags;

DWORD time;

ULONG_PTR dwExtraInfo;

} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;

Có ý nghĩa như trong Phụ lục Sự kiện bàn phím.

Ý nghĩa tham số:

[in]

vkCode : mã phím ảo từ 1-254.

scanCode: mã quét phần cứng.

flags: cờ phím mở rộng, cờ sự kiện thêm vào, mã ngữ cảnh, và cờ chuyển

đổi trạng thái. Ứng dụng dùng các giá trị sau để kiểm tra cờ nhấn phím

Value Purpose

LLKHF_EXTENDED Kiểm tra cờ mở rộng.

LLKHF_INJECTED Kiểm tra cờ thêm sự kiện.

LLKHF_ALTDOWN Kiểm tra mã ngữ cảnh.

LLKHF_UP Kiểm tra cờ chuyển trạng thái.

92

Bảng 3-1 Giá trị khảo sát phím mở rộng

cho biết phím có là phím mở rộng hay không, chẳng hạn như phím 0

chức năng hay phím bên bảng số (numpad). Giá trị 1 nếu đúng, 0 nếu

sai.

1-3 Dành riêng.

Cho biết sự kiện này có phải do được thêm vào không (chứ không 4

phải do từ bàn phím gõ). Giá trị 1 nếu đúng, 0 nếu sai.

Cho biết mã ngữ cảnh, phím alt có được nhấn hay không. Giá trị 1 5

đúng, nếu

0 nếu sai.

6 Dành riêng.

7 Cho biết trạng thái phím. Giá trị 0 nếu phím nhấn và một nếu phím

được thả.

time Cho biết tem thời gian của thông điệp.

dwExtraInfo Cho biết các thông tin đi kèm thêm với thông điệp.

So sánh với các tham số của WH_KEYBOARD, ta cần giả lập wParam,

lParam của WH_KEYBOARD từ wParam, lParam của WH_KEYBOARD_LL.

wParam: khá dễ dàng, wParam của WH_KEYBOARD chính là vkCode

trong cấu trúc KBDLLHOOKSTRUCT do lParam của WH_KEYBOARD_LL trỏ

đến.

lParam: phức tạp hơn một chút, ở đây ta phải giả lập lại giá trị DWORD của

lParam trong WH_KEYBOARD từ cấu trúc KBDLLHOOKSTRUCT do lParam

của WH_KEYBOARD_LL trỏ đến. Hàm MakeFakelParam sẽ giúp ta làm điều này:

LPARAM MakeFakelParam(PKBDLLHOOKSTRUCT pKb)

Hàm có tác dụng chuyển đổi giá trị lParam trong cấu trúc

KBDLLHOOKSTRUCT sang giá trị lParam của WH_KEYBOARD.

Tuy thế, mọi việc vẫn chưa kết thúc. Rắc rối xảy ra khi ta nhấn phím ALT.

Phím ALT sẽ nhận biết được nếu ta nhấn phím mà không kèm theo một phím khác.

93

Phím sẽ không biết được nếu ta nhấn kèm với phím khác vì khi đó, driver bàn phím

sẽ thông dịch phím ALT thành mã ngữ cảnh. Vì vậy, đối với riêng tình huống này ta

phải xử lý riêng:

So sánh thêm mã ngữ cảnh:

if( (g_bHook[VK_LMENU]) || (g_bHook[VK_RMENU]) )

if(p->flags & LLKHF_ALTDOWN) // co nhan kem alt voi phim nay

return 1;

Như vậy bài tóan tinh chế 2 đã được giải quyết hoàn chỉnh.

chèn hình

Thử nghiệm:

Chương trình chạy tốt yêu cầu đề ra. Lưu ý rằng do tính chất là một hook cấp

thấp, nên vấn đề nhận biết số lần lặp lại phím khá phức tap. Ta có thể bỏ qua việc

này vì ứng dụng thực sự của ta không cần đến.Vấn đề còn lại là ghi nhận phím, một

keylogger đơn giản, ít phức tạp hơn nhiều.

Hình 3-4 Tinh chế 2

3.1.5.4 Tinh chế 3:

Xây d(cid:127)ng m(cid:127)t (cid:127)ng d(cid:127)ng cài (cid:127)(cid:127)t m(cid:127)t hook toàn c(cid:127)c. Khi (cid:127)ng d(cid:127)ng ch(cid:127)y, xu(cid:127)t ra màn hình ký t(cid:127) ng(cid:127)(cid:127)i dùng gõ.

Ta cần lưu ý kỹ thuật lập trình truyền thông điệp chứa dữ liệu ký tự phím gõ

từ hook procedure đến cửa sổ xử lý. Điều này có thể thực hiện được khi lúc ban đầu

94

khởi tạo hook ta cần cho hook biết cần kiểm sóat bao nhiêu phím (cả bàn phím),

handle cửa sổ chính, loại thông điệp (ứng dụng ta không cần quan tâm nên ta chỉ

cần thông điệp WM_KEYDOWN), các loại cửa sổ cần kiểm sóat (mọi cửa sổ), các

phím kết hợp kèm theo (ta không quan tâm). Tất cả các thông tin trên được gọi là

một bộ kiểm sóat (entry). Hàm LogKeyboard sẽ giúp ta làm điều này:

LRESULT CKeyLogClient::LogKeyboard(HWND hWnd)

Hàm sẽ gọi hàm AddKeyEntry, là một hàm trong DLL. Hàm có tác dụng lưu

trữ các dữ liệu trên. Khi đó, cài đặt hook xong ta chỉ việc đợi kết quả gởi tới cửa sổ

xử lý. Dĩ nhiên, hook procedure cần sửa lại để thông báo cho cửa sổ cài đặt hook

biết có thông điệp mã phím cần xử lý (sử dụng hàm PostMessage gởi thông điệp tự

định nghĩa cho cửa sổ chính với handle cửa sổ chính nhận được từ hàm

LogKeyboard).

LRESULT CALLBACK KeyboardProc(INT nCode, WPARAM wParam,

LPARAM lParam)

Thử nghiệm:

Như vậy, ta đã hoàn tất được mục tiêu đề ra ban đầu. Mặc dù chương trình

hoàn chỉnh phải bao gồm nhiều kỹ thuật lập trình thú vị khác, nó lại không nằm

trong phạm vi tìm hiểu mà mục tiêu ta cần. Chương trình hoàn chỉnh còn có thêm

khả năng sử dụng hook cho đồng thời tối đa 256 tiến trình và tối đa 1024 bộ kiểm

sóat. Phần việc còn lại chỉ cần thay đổi một ít mã nguồn để tích hợp vài chương

trình chính.

95

Hình 3-5 Tinh chế 3

3.2 Xây dựng màn hình che:

Trong quá trình thực hiện phần mềm, có một yêu cầu cần thiết cho chương

trình quản lý phòng máy là cần phải ngăn chặn người dùng không dùng máy khi

chưa đăng ký với người quản trị để sử dụng. Một điều thực tế hiển nhiên là các máy

tính trong phòng máy phải luôn bật máy sẵn sàng. Vì vậy, ta cần xây dựng một màn

hình che trên màn hình để người dùng không thể tương tác với máy.

3.2.1 Phân tích sơ lược:

Ta nhận thấy rằng để tương tác với máy tính, thông thường người dùng sẽ sử

dụng hai thiết bị tương tác là mouse và bàn phím. Ta không cần quan tâm về các

loại thiết bị tương tác khác vì thông thường các phòng máy chỉ cần hai thiết bị nêu

96

trên là đủ. Vì vậy, ta sẽ xem xét các tương tác của người dùng để sử dụng máy tính

bằng hai thiết bị trên.

Sau khi khảo sát, quy trình sử dụng máy thông thường sẽ là:

1. Bật máy lên

2. Nếu có icon chương trình cần chạy trên desktop, kích hoạt chương trình.

3. Nếu chương trình không có trên desktop, người dùng sẽ lục tìm trên máy

bằng nhiều cách khác nhau như :

a. Nhấn Start, dò trên All Programs.

b. Nhấn Start, chạy Run, mở gõ chương trình cần chạy.

c. Chạy My Computer, dò chương trình trong cây thư mục.

d. Mở Windows Explorer, dò chương trình trong cây thư mục.

e. …

4. Khi sử dụng xong chương trình, người dùng đóng chương trình lại.

5. Quay trở lại bước 2 Vòng lặp sẽ xảy ra cho đến khi người dùng sử dụng

xong máy tính.

6. Tắt máy tính.

Các bước 1 và 6 có thể được bỏ qua. Ta sẽ xem xét các bước từ 2 đến 6. Dễ

dàng nhận thấy rằng mọi tương tác của người dùng thông thường đều phải

thông qua desktop. Nếu ta làm cách nào đó ngăn chặn việc tương tác của

người dùng trên desktop, ta sẽ đạt được mục tiêu đề ra. Từ đây, ta sẽ đưa ra các

khảo sát cụ thể cho mỗi thiết bị mouse và bàn phím.

3.2.1.1 Tương tác bằng mouse:

Đây là thiết bị chủ yếu người dùng sẽ sử dụng để tương tác với máy tính.

Phần lớn người dùng thông thường sẽ không biết sử dụng máy, hoặc sẽ rất khó khăn

khi sử dụng máy mà không có mouse. Do tính phổ thông và cần thiết như thế, người

dùng sẽ phụ thuộc rất nhiều vào mouse.

Vẫn theo ý tưởng đề ra ở trên, ta để ý rằng thực chất desktop chỉ là một cửa

sổ của Windows, trên đó, mọi ứng dụng sẽ được chạy (mọi cửa sổ ứng dụng được

97

mở trên desktop đều là cửa sổ con của nó). Nếu có một cửa sổ nào đó nằm chồng

lên trên desktop, và cửa sổ đó đang kích hoạt, thì người dùng sẽ tương tác với cửa

sổ đó chứ không thể tương tác với desktop. Để có thể tương tác trở lại với desktop,

người dùng phải click mouse trái lên trên desktop (trong trường hợp cửa sổ bình

thường), nhấn nút Minimise trên thanh tiêu đề của cửa sổ (trong trường hợp cửa sổ

bình thường hoặc đang phóng to hết cỡ). Điều gì sẽ xảy ra nếu người dùng không

còn những khả năng trên :

o không thể click chuột trái lên trên desktop vì cửa sổ đang được phóng to hết

cỡ (maximized), che mất cả desktop và cả thanh taskbar .

o không thể thu nhỏ cửa sổ lên trên thanh taskbar, phục hồi cửa sổ lại kích

thước thông thường, và tắt cửa sổ đi vì cửa sổ không có thanh tiêu đề.

Đến đây, ta đã thấy rõ cách làm. Điều duy nhất cần làm bây giờ là :

o tạo một cửa sổ không có thanh tiêu đề.

o kích hoạt cửa sổ mỗi khi máy vừa khởi động xong.

o “căng” kích cở của cửa sổ sao cho vừa khít với desktop.

Để làm được điều này, ta sẽ sử dụng các kỹ thuật và hàm thông thường được

cung cấp sẵn bởi Windows mà ta sẽ đề cập kỹ ở phần cài đặt. Bây giờ, đã đến lúc đề

cập đến bàn phím.

3.2.1.2 Tương tác với bàn phím:

Đây là thiết bị quan trọng thứ hai sau mouse để người dùng tương tác với

desktop. Phần lớn người dùng thông thường chỉ sử dụng bàn phím nhiều khi họ sử

dụng máy tính là đánh văn bản. Trong phòng máy tính Café Internet, bàn phím

được dùng để chat, nhập thông tin người dùng trong lúc lướt web… Chỉ có một số

nhỏ người dùng am hiểu rõ và ghi nhớ các phím tắt do Windows gán để tương tác

với desktop. Chẳng hạn, xem bảng so sánh các thao tác bằng mouse và bàn phím

qua hai thao tác hay dùng là mở Control Panel và shutdown máy:

Bằng mouse Bằng bàn phím

98

1. Mở Control Panel 1. Mở Control Panel

a. Nhấn Win key, hoặc Ctrl-Esc a. Nhấn Start

b. Nhấn phím r, kích hoạt cửa sổ Run

c. Gõ “control” trong ô Open (không có dấu “”) b. Chọn All Programs

d. Nhấn Enter c. Chọn Control Panel

2. Shutdown máy: 2. Shutdown máy :

a. Nhấn Win key, hoặc Ctrl-Esc. a. Nhấn Start

b. Nhấn phím r, kích hoạt cửa sổ Run. b. Chọn Turn off

c. Gõ “shutdown /s /t 0” trong ô Open (không có Computer

dấu “”) c. Chọn tiếp Turn off

d. Nhấn Enter

Bảng 3-2 So sánh tương tác giữa mouse và bàn phím

Tùy thuộc vào cấu hình các phiên bản Windows mà các bước thực hiện có thể khác

đôi chút, ở đây ta sử dụng WindowsXP chế độ taskbar là “Start menu”, chế độ log

off là “Using Welcome Screen”.)

Nhìn chung các thao tác bằng bàn phím khá phức tạp hơn bằng mouse, tựu

trung lại chỉ cần nhớ phím và tổ hợp phím thực thi, câu lệnh, và làm một việc duy

nhất là …gõ. Do vậy, ta chỉ cần làm một việc duy nhất là vô hiệu hóa toàn bộ phím

bấm trên bàn phím là xong mà ta sẽ đề cập kỹ ở phần cài đặt.

3.2.2 Cài đặt:

Ta sẽ thực hiện những bước đề ra như ở trong phần 1.2.1 Phân tích sơ lược

lần lượt cho mỗi thiết bị.

3.2.2.1 Tương tác với mouse:

Ta sẽ tạo một cửa sổ. Tuy nhiên, cửa sổ theo dạng tài liệu (document) như

WinWord, Windows Explorer… không phù hợp cho mục tiêu. Cái ta cần sẽ là một

cửa sổ dạng hộp thoại (dialog), vì ta về sau có thể cần chèn hình ảnh giới thiệu. Vả

lại, ta cần một cửa sổ càng đơn giản càng tốt (ít cấu hình sẵn), hỗ trợ thiết kế trực

99

quan… thì trong Microsoft Visual Studio 6.0 viết chương trình bằng MFC, loại

project theo Dialog-based là thích hợp nhất.

Sau khi tạo một hộp thoại xong, ta cần cho cửa sổ “nổi” lên trên tất cả cửa sổ

khác kể cả desktop và thanh taskbar và “căng” kích cỡ chiếm hết cả màn hình. Hàm

API SetWindowPos sẽ giúp ta điều này.

Tuy thế, ta sẽ không gọi trực tiếp hàm API SetWindowPos mà gọi thông qua

phương thức của CWnd, lớp cha của lớp cửa sổ thoại, SetWindowPos:

Phương thức chỉ khác hàm API ở chỗ chỉ có 6 tham số ứng lần lượt với 6

tham số cuối của hàm API. Phương thức sẽ thực thi bằng cách gọi lại hàm API và

thêm tham số đầu tiên của hàm API băng handle cửa sổ có sẵn cửa sổ lớp hộp thoại

m_hWnd.

Đến đây, có một vấn đề nhỏ cần giải quyết là lấy được kích thước của

desktop, hay nói cách khác là độ phân giải của màn hình. Ta không thể lấy cố định

kích thước, ví dụ là 800x600, vì mỗi màn hình sẽ được người dùng sẽ thay đổi độ

phân giải cho phù hợp với mắt nhìn. Do vậy, có hai cách giải quyết :

a. Đọc trực tiếp các giá trị độ dài và độ rộng của màn hình bằng hàm API

GetSystemMetrics:

Áp dụng hàm trong chương trình như sau:

int xScrn = ::GetSystemMetrics(SM_CXSCREEN);

int yScrn = ::GetSystemMetrics(SM_CYSCREEN);

SetWindowPos(&wndTopMost, 0, 0, xScrn, yScrn,

SWP_SHOWWINDOW);

Đọan mã trên đặt trong phương thức khởi tạo của cửa sổ hộp thoại, tham số

&wndTopMost nhằm đặt cửa sổ vào dãy thứ tự các cửa sổ dạng “nổi trội”, các tham

số sau có ý nghĩa là dời cửa sổ về góc trên bên phải màn hình, độ rộng và dài bằng

độ phân giải màn hình, kích hoạt và hiện cửa sổ.

b. Đọc các giá trị độ rộng và dài từ hai hàm API CreateDC,

GetDeviceCaps. Dùng cách này có tiện lợi khi hệ thống có nhiều màn hình hiển

thị:

100

hàm API CreateDC: tạo ngữ cảnh thiết bị

hàm API GetDeviceCaps: lấy các thông số của thiết bị.

Áp dụng mã vào chương trình như sau:

HDC hScrDC;

hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);

int xScrn, yScrn;

xScrn = GetDeviceCaps(hScrDC, HORZRES);

yScrn = GetDeviceCaps(hScrDC, VERTRES);

//resize cho lon nhat . Day la topmost window

SetWindowPos(&wndTopMost, 0, 0, xScrn, yScrn,

SWP_SHOWWINDOW);

Hai dòng đầu tạo một HDC cho thiết bị màn hình hiển thị, do tính chất đặc

biệt của màn hình mà hàm chỉ cần nhận tham số tên “DISPLAY” là có thể trả về kết

quả.

Ba dòng kế tiếp có tác dụng lấy độ rộng và độ dài của màn hình. Dòng cuối

là gọi phương thức SetWindowPos như cách 1.

Có một lưu ý nhỏ ở đây là ta vẫn có thể sử dụng thay thế hàm

SetWindowPos bằng một hàm API khác là MoveWindow. Để biết chi tiết hàm, xem

thêm trong Phụ lục Các hàm API hữu ích sử dụng trong chương trình. Hàm

API này tuy có chức năng tương tự với SetWindowPos nhưng hàm lại không có

chức năng quản lý việc “nổi” lên trên cửa sổ khác.Mặc dù theo thiết kế ban đầu khi

khởi động xong, chỉ có một cửa sổ màn hình che phủ toàn bộ màn hình, rất có khả

năng người dùng nhanh tay kích hoạt một cửa sổ nào đó trên desktop. Khi ấy, sử

dụng hàm MoveWindow lại không làm cửa sổ “nổi” lên trên tất cả các cửa sổ còn

lại. Hàm SetWindowPos lại có thêm tác dụng hữu ích này.

Thử nghiệm:

Chương trình vô hiệu hóa tuyệt đối việc tương tác của người dùng với

desktop bằng mouse. Chỉ còn lại một việc nữa phải làm là vô hiệu hóa bàn phím.

101

Hình 3-6 Màn che mouse

3.2.2.2 Tương tác bằng bàn phím:

Mục tiêu ban đầu là không cho người dùng gõ những phím tắt kích hoạt

chương trình. Tuy nhiên, ta không cần vô hiệu hóa cả bàn phím. Điều này rất lãng

phí công sức. Thực chất, ta thực hiện mục tiêu dưới điều kiện hoàn thành ngăn chặn

tương tác với mouse. Vì vậy các loại tương tác làm cho xuất hiện các chương trình

thông thường như Windows Explorer (Win key + E)… không làm ta quan tâm vì

các cửa sổ chương trình đó không thể “nổi” bằng cửa sổ màn hình che. Vì vậy, chỉ

còn lại các loại phím và tổ hợp phím tắt “nhạy cảm” cấp thấp mà thôi. Các loại

phím tắt đó là:

o Win key : có tác dụng bật Start menu.

o Alt + Tab : có tác dụng đổi cửa sổ đang hoạt động.

o Alt + Esc : có tác dụng kích hoạt cửa sổ kế trên thanh taskbar.

102

o Ctrl + Esc: có tác dụng tương tự Win key

o Ctrl + Shift + Esc : có tác dụng bật Task Manager.

o Esc : đây là vấn đề về kỹ thuật làm, theo thiết kế ta tạo một cửa sổ hộp thoại

đơn giản, nên chịu tác dụng của phím Esc, có tác dụng tắt cửa sổ màn che.

o Alt + F4 : có tác dụng tắt cửa sổ màn hình che.

o Ctrl + Alt + Del : có tác dụng bật Task Manager, hay hộp lựa chọn tùy theo

cấu hình Windows (đây là tổ hợp phím gây “nhức đầu” nhiều nhất, ta sẽ đề

cập kỹ trong phần sau).

o Ctrl + Shift + Esc : bật Task Manager.

May mắn thay, trong 7 tổ hợp phím đầu, ta dễ dàng loại bỏ khi sử dụng kỹ

thuật lập trình bằng hook, xem chi tiết về kỹ thuật này trong 3.1 Kỹ thuật lập trình

sự kiện và hook và mã nguồn chương trình. Ta chỉ áp dụng xây dựng một hook

đơn giản lọc bỏ trong quá trình đợi đăng nhập và loại bỏ khi đăng nhập xong. Tuy

nhiên, với 2 tổ hợp phím cuối cùng, Ctrl + Alt + Del và Ctrl + Shift + Esc (về sau ta

gọi tắt chỉ một mình tổ hợp Ctrl + Alt + Del vì tổ hợp Ctrl + Shift + Esc cũng có

tính năng tương tự), khá phức tạp. Ta phải hiểu rõ cơ chế truyền gởi thông điệp Ctrl

– Alt – Del.

Hook bàn phím không thể bắt được tổ hợp phím Ctrl – Alt – Del ! Tại sao ?

Vì chính bản thân hệ điều hành Windows không hề gởi tổ hợp phím này cho hook

chain. Nó đã được chặn bắt và xử lý ở mức thấp hơn ở hệ thống và không bao giờ

được gởi lên ứng dụng. Ứng dụng nếu có cài đặt cũng chỉ nhận được các phím Ctrl,

Alt, và Del rời rạc chứ không phải là tổ hợp Ctrl – Alt – Del.

Tổ hợp phím sau đó sẽ gởi đến cơ chế khởi động đăng nhập của Windows,

gọi là Winlogon, gồm 3 thành phần : thành phần thực thi (“winlogon.exe”), thư viện

liên kết động “Chứng thực và nhận dạng theo cơ chế đồ họa” (Graphical

Identification and Authentication GINA) (“msgina.dll”), và các thành phần mạng.

Tham khảo các tài liệu, ta tìm thấy các cách khống chế tổ hợp Ctrl – Alt –

Del, một số cách dựa trên việc khống chế một trong hai thành phần đầu trong cơ

chế khởi động đăng nhập của Windows như sau:

103

• Giả lập “lừa” hệ điều hành rằng đang có một screensaver đang chạy, tổ hợp

phím được gởi nhưng không kích hoạt Task Manager. Tuy nhiên, cách này

chỉ có tác dụng ở các phiên bản hệ điều hành Win98, không có tác dụng trên

WinXP. Cách này cũng rất hạn chế khi chỉ có tác dụng khi có thiết lập hệ

thống phù hợp, một số tài liệu cho rằng cả phiên bản hệ điều hành Win98

• Vô hiệu hóa Task Manager bằng chính sách (policy). Cách này không hề xử

cũng không có tác dụng !.

lý ở “gốc”, chặn bắt thông điệp Ctrl – Alt – Del, mà xử lý ở “ngọn”, đặt

chính sách hệ thống ngăn chặn kích hoạt Task Manager. Cách này đơn giản

nhưng không dùng được vì thông điệp thông báo :

Hình 3-7 Thông báo của policy về việc vô hiệu hóa Task Manager

• Bắt thông điệp ở tận “gốc” khi xây dựng driver thiết bị bàn phím. Lúc đó,

khá bực mình, lại còn làm xuất hiện Start Menu.

phải sử dụng Device Development Kit (bộ phát triển thiết bị). Đây là lĩnh

vực lập trình hoàn toàn mới, với thời gian nghiên cứu không cho phép, ta bỏ

• Viết một GINA stub. GINA là một thư viện liên kết động mà Winlogon dùng

qua khả năng này.

để chứng thực người dùng. Đây là một cách khá hay, nhưng nó lại làm thay

đổi cách đăng nhập của người dùng đồng thời vô hiệu hóa màn hình

Welcome, và chớp màn hình mỗi khi người dùng nhấn Ctrl – Alt – Del. Tuy

ta không sử dụng cách này nhưng có thể xem thêm về kỹ thuật này trong

• Tạo một desktop mới và chuyển sang desktop mới này. Vì kích hoạt Task

Phụ lục GINA stub – kỹ thuật xây dựng.

Manager bằng tổ hợp phím Ctrl – Alt – Del chỉ làm xuất hiện Task Manager

104

trên “Default” desktop (desktop cũ), nên trên desktop mới sẽ không có xuất

hiện. Cách này khá hiệu quả khi ta xây dựng màn hình che bên desktop mới,

người dùng đăng nhập vào thì trở lại desktop cũ. Khuyết điểm nhỏ của cách

này là hơi phức tạp về mặt lý thuyết cài đặt chương trình, và người dùng

đăng nhập vào thành công sẽ thấy Task Manager hiện ra mặc dù trước đó có

vẻ việc nhấn Ctrl – Alt – Del không có tác dụng. Tuy ta không sử dụng cách

này nhưng có thể xem thêm về kỹ thuật này trong Phụ lục Tạo thêm và sử

• Kế thừa, trở thành lớp con của lớp cửa sổ SAS trong tiến trình Winlogon. Để

dụng Desktop mới.

làm được điều này, mã phải được “chích” (inject) vào tiến trình Winlogon và

sau đó tạo lớp con kế thừa Windows Procedure. Kỹ thuật này không tương

thích với Windows 95/98/Me. Ta sẽ sử dụng kỹ thuật này để vô hiêu hóa

tổ hợp phím Ctrl – Alt - Del.

Module xây dựng gồm có hai phần lớn : tạo lớp con kế thừa lớp cửa

sổ SAS của Winlogon.

* Tạo lớp con kế thừa lớp cửa sổ SAS của Winlogon:

Hàm API SetWindowLong sẽ giúp ta thực hiện điều này:

Áp dụng hàm vào trong chương trình:

SetWindowLong(hWnd, GWL_WNDPROC, NewWindowProc);

Lời gọi chỉ có tác dụng cho các cửa sổ được tạo bởi cùng ứng dụng

gọi hàm (địa chỉ hàm NewWindowProc chỉ có nghĩa với tiến trình gọi hàm

SetWindowLong). Như vậy, ta sẽ dùng một cách nào đó ánh xạ được điạ chỉ của

NewWindowProc vào trong không gian địa chỉ của tiến trình ở xa và chuyển địa

chỉ đó đến lời gọi hàm SetWindowLong. Để có thể hiểu cơ chế nạp một chương

trình vào bộ nhớ, cũng như định nghĩa về không gian địa chỉ của tiến trình, xem

thêm Phụ lục Quá trình nạp một hook DLL toàn cục.

Bây giờ, ta sẽ bàn về kỹ thuật injection.

* Kỹ thuật injection:

105

Khả năng ứng dụng của kỹ thuật injection rất mạnh mẽ và hữu ích.

Ưu điểm này cũng lại là khuyết điểm. Vì càng có nhiều khả năng ứng dụng mà

không bị hạn chế, kỹ thuật injection đòi hỏi các lập trình viên cần phải lập trình cực

kỳ cẩn thận các đọan mã mà họ sẽ “chích” vào tiến trình ở xa. Mọi hành động

“chích” lầm sẽ dẫn đến hậu quả cực kỳ nguy hiểm như crash chương trình ở xa, treo

máy… Tuy nhiên, việc lập trình thành công bằng kỹ thuật injection sẽ gợi mở

nhiều khả năng lập trình thú vị như : xem mật khẩu dạng * trên một cửa sổ khác,

Hình 3-8 Ứng dụng xem mật khẩu từ cửa sổ khác

điều khiển hoạt động của các tiến trình hệ thống Windows như : giấu tên tiến trình

đang chạy trong hai tab Applications” và “Processes” của Task Manager, … đặc

biệt là ứng dụng mà ta cần là vô hiệu hóa Ctrl – Alt – Del.

Vậy thực chất kỹ thuật injection là gì ? Kỹ thuật ánh xạ bộ nhớ (mã chương

trình) vào trong không gian địa chỉ của một tiến trình ở xa được gọi là kỹ thuật

injection.

• Registry. Để “chích” một DLL vào một tiến trình, chỉ cần đơn giản thêm tên

Việc injection có thể thực hiện bởi một trong những cài đặt sau:

DLL đó vào trong khóa registry:

HKLM\Software\Microsoft\Windows NT\

106

CurrentVersion\Windows\AppInit_DLLs:STRING

• Hook. Cách này hỗ trợ trên mọi phiên bản Windows.

• Sử dụng CreateRemoteThread()/LoadLibrary(), chỉ đúng với

chỉ hỗ trợ trên Windows NT trở lên.

• Sao chép mã trực tiếp vào tiến trình ở xa bằng WriteProcessMemory()

Windows NT và cao hơn.

và thực thi nó bằng hàm CreateRemoteThread(), chỉ đúng với

Windows NT và cao hơn.

Mức độ cẩn thận trong lập trình tăng dần từ trên xuống trong 4 cài đặt của kỹ

thuật, tỉ lệ nghịch với việc tiêu tốn tài nguyên (giảm dần từ trên xuống). Cơ chế

hook vẫn áp dụng được trong kỹ thuật này nhưng việc áp dụng nó khá tiêu tốn tài

nguyên hệ thống. Ta sẽ thực hiện phương án cuối để áp dụng kỹ thuật injection cho

cài đặt trong phần mềm. Phương án 3 cũng khả thi nhưng lại không ổn định, tùy

thiết lập của máy mà phương án thành công hay không, có thể xem thêm phương án

này trong mã nguồn chương trình.

Ở đây, ta sẽ mô tả cài đặt cuối :

Chương trình sử dụng cài đặt cuối qua hai hàm InjectCode, và

EjectCode. InjectCode thực hiện việc sao chép dữ liệu và trong tiến trình của

cửa sổ SAS. Các dữ liệu này là : InjectFunc, “khung” thực thi của tiểu trình,

GetSASWnd, tìm handle của cửa sổ SAS, SASWindowProc, hàm window

procedure của lớp con kế thừa, INJDATA, các dữ liệu đầu vào.

Hàm InjectCode

int InjectCode ()

Bỏ qua các chi tiết rườm rà về kỹ thuật (cấp phát bộ nhớ bên tiến trình ở xa,

kỹ thuật lấy vùng nhớ …) thì hàm InjectCode làm những động tác sau:

o Lấy địa chỉ hàm FindWindowA trong DLL USER32.DLL.

o Mở tiến trình winlogon.exe với truy cập toàn quyền.

o Sao chép dữ liệu INJDATA với khởi tạo gồm tên lớp "SAS Window class",

tên cửa sổ "SAS window", địa chỉ hàm FindWindowA vào tiến trình ở xa.

107

o Sao chép hàm GetSASWnd vào trong tiến trình ở xa.

o Tạo tiểu trình thực hiện việc tìm kiếm handle của cửa sổ SAS.

o Nếu thành công, sẽ trả về handle cửa sổ SAS.

o Sao chép nội dung hàm SASWndProc vào trong tiến trình ở xa.

o Sao chép dữ liệu INJDATA với khởi tạo gồm địa chỉ hàm SetWindowLong

(tùy theo tiến trình ở xa có sử dụng Unicode hay không mà sẽ chép tương

ứng hàm dạng SetWindowLongA hay SetWindowLongW),

CallWindowProc (tùy theo tiến trình ở xa có sử dụng Unicode hay không

mà sẽ chép tương ứng hàm dạng CallWindowProcA hay

CallWindowProcW), SASWndProc.

o Trong SASWndProc, cần sử dụng dữ liệu trong INJDATA nhưng đây là

một hàm callback nên tham số đầu vào không thể tùy biến, ta không thể

truyền tường minh dữ liệu này. Vì vậy, ở đây, ta đã biết được địa chỉ của dữ

liệu đầu vào INJDATA, và cả nội dung hàm SASWndProc đã được ghi vào

vùng nhớ bên tiến trình ở xa, ta phải thực hiện động tác ghi trực tiếp giá trị

biến nội tại sẽ lưu địa chỉ dữ liệu đầu vào INJDATA, bằng cách tìm trong

vùng nhớ ở xa đã ghi nội dung hàm SASWndProc từng DWORD một. Dĩ

nhiên biến nội tại này đã lưu một giá trị đặc biệt để có thể tìm ra.

o Sao chép nội dung hàm InjectFunc

tiểu trình thực hiện nội dung hàm InjectFunc: dùng o Tạo

SetWindowLong thay window procedure mới.

o Nếu thành công, công việc hoàn tất.

Hàm InjectFunc

Chức năng: tạo lớp con kế thừa, thay đổi hàm window procedure mới cho

cửa sổ SAS.

static DWORD WINAPI InjectFunc (INJDATA *pData)

Hàm window procedure mới chính là SASWindowProc. Ta không thể lấy

dữ liệu từ tiến trình ở xa (ví dụ như truy cập hàm SetWindowLong…) nên mọi dữ

liệu đầu vào phải chuẩn bị sẵn và “chích” vào tiến trình, tại đây, lần lượt các hàm sẽ

108

sử dụng các dữ liệu này. Ở đây, InjectFunc sử dụng địa chỉ hàm

SetWindowLong trong INJDATA

Ý nghĩa tham số:

pData: dữ liệu đầu vào, sẽ được giải thích ở phần sau.

Hàm GetSASWnd

Chức năng :lấy handle của cửa sổ SAS.

static HWND WINAPI GetSASWnd (INJDATA *pData)

Hàm SASWindowProc

LRESULT CALLBACK SASWindowProc(HWND hWnd, UINT uMsg,

WPARAM wParam, LPARAM lParam)

Nếu đến đây mọi việc “đột nhập” đều suôn sẻ, các công việc sau đây sẽ được

thực hiện tiếp trong đoạn mã vừa sao chép (là nội dung các hàm nêu ở trên, các

• Lấy handle của cửa sổ SAS :

bước sau đều thực hiện trong không gian địa chỉ ảo của tiến trình ở xa):

hSASWnd = FindWindow("SAS Window class", "SAS window");

FindWindow là một hàm API khá hữu ích, được dùng để tìm handle của các

• Tạo lớp con kế thừa window procedure của cửa sổ SAS:

cửa sổ top-level nếu biết tên cửa sổ và tên lớp.

• Trong NewSASWindowProc(), bắt thông điệp WM_HOTKEY và trả về 1

SetWindowLong(hSASWnd, GWL_WNDPROC, NewSASWindowProc);

cho tổ hợp phím Ctrl – Alt – Del.

LRESULT CALLBACK NewSASWindowProc(HWND hWnd, UINT uMsg,

WPARAM wParam, LPARAM lParam)

{

if (uMsg == WM_HOTKEY)

{

// Ctrl+Alt+Del

if (lparam == MAKELONG(MOD_CONTROL | MOD_ALT, VK_DELETE))

return 1;

109

}

return CallWindowProc(OldSASWindowProc, hWnd, wParam, lParam);

}

Hình 3-9 Màn che mouse và bàn phím

110

3.3 Tương tác với hệ thống – Điều khiển danh sách các ứng

dụng đang chạy:

Trong quá trình thực hiện phần mềm, có một yêu cầu quản trị hệ thống là

người quản trị muốn biết tại thời điểm hiện tại, người dùng đang mở những ứng

dụng gì. Người quản trị có thể xem danh sách các ứng dụng đó, đồng thời có thể

thay đổi bằng cách thêm (mở một ứng dụng mới), bớt (tắt một ứng dụng đang

chạy). Yêu cầu này đòi hỏi cần phải tìm hiểu cơ chế quản lý cửa sổ trong hệ điều

hành Windows.

3.3.1 Các hàm dạng Enum_ và cơ chế gọi ngược (callback) của

Windows:

Có một số dữ liệu về hệ thống mà chúng ta khi cần truy cập trực tiếp sẽ rất

khó khăn, ví dụ như có bao nhiêu font chữ trên hệ thống ?, có bao nhiêu cửa sổ

đang họat động trên hệ thống ?... vì các dữ liệu dạng này đều do hệ thống nắm giữ,

và hệ thống không muốn chúng ta để ý nhiều về chi tiết quản lý của nó. Do đó, hệ

điều hành Windows cung cấp một số các hàm liệt kê sẽ giải đáp những thắc mắc

trên của chúng ta. Vấn đề còn lại là hệ thống không biết chúng ta sẽ xử lý như thế

nào với những dữ liệu mà nó cung cấp vì dữ liệu dạng này không được tường minh

(có thể không có hoặc có rất nhiều), hệ thống phải kiểm tra và trả về từng thành

phần dữ liệu một…

Câu trả lời là hệ điều hành Windows sẽ cung cấp một cơ chế gọi ngược

(callback). Nói một cách đơn giản, chúng ta sẽ thông báo với hệ thống rằng khi hệ

thống cung cấp các dữ liệu mà ta yêu cầu thì hãy xử lý theo những công việc mà ta

đề ra. Hàm mà chứa các công việc ta giao cho hệ thống làm được gọi là hàm gọi

ngược (callback function).

Một hàm gọi ngược là một hàm do ứng dụng của người dùng tự định nghĩa

và được thực thi bởi hệ điều hành mỗi khi có sự kiện liên quan đến hàm xảy ra.

111

3.3.2 EnumWindows

Để lấy được danh sách các ứng dụng đang chạy, ta sẽ sử dụng cơ chế gọi

ngược. Theo cơ chế gọi ngược, hệ điều hành Windows cung cấp một loạt các hàm

liệt kê bắt đầu bằng từ Enum (enumerate : liệt kê) như

EnumFontFamilliesEx, EnumForms và … EnumWindows.

EnumWindows chính là hàm ta cần:

Hàm EnumWindows

Chức năng: liệt kê tất cả cửa sổ top-level trên màn hình bằng cách trả về

handle của từng cửa sổ một cho một hàm gọi ngược của ứng dụng định nghĩa. Việc

liệt kê sẽ kết thúc khi đến cửa sổ cuối hoặc hàm gọi ngược trả về FALSE.

BOOL EnumWindows(

WNDENUMPROC lpEnumFunc,

LPARAM lParam

);

Ý nghĩa tham số:

[in]

lpEnumFunc : trỏ đến hàm gọi ngược.

lParam : giá trị do ứng dụng định nghĩa và chuyển cho hàm gọi ngược.

Giá trị trả về:

[out]

Nếu thành công, trả về khác 0.

Nếu thất bại, trả về 0. Để biết lỗi, gọi GetLastError.

Định nghĩa hàm gọi ngược của EnumWindows.

Chức năng: hàm gọi ngược của EnumWindows.

BOOL CALLBACK EnumWindowsProc(

HWND hwnd,

LPARAM lParam

);

Ý nghĩa tham số:

112

[in]

hwnd : handle của top-level windows.

lParam : giá trị do ứng dụng định nghĩa và chuyển cho hàm gọi ngược (là

tham số lParam trong hàm EnumWindows).

Giá trị trả về:

[out]

Để tiếp tục liệt kê cửa sổ, hàm phải trả về TRUE. Ngược lại, trả về FALSE.

Có một lưu ý nhỏ ở đây : ta vẫn có thể sử dụng hàm tương tự là

EnumDesktopWindows, là hàm liệt kê tất cả cửa sổ trên desktop. Tuy nhiên, ta có

thể lấy thiếu một số cửa sổ người dùng khi sử dụng hàm này. Ngược lại, hàm

EnumWindows lại có nhược điểm nhỏ là lấy dư các cửa sổ của hệ thống. Các cửa

sổ này không phải là các cửa sổ chúng ta cần, vì vậy ta phải có các thao tác loại bỏ

chúng đi.

3.3.3 Lấy danh sách các ứng dụng đang chạy:

Ta chỉ cần viết một hàm gọi ngược thực hiện các công việc sau:

o Nếu là cửa sổ gọi hàm EnumWindows, bỏ qua.

o Nếu là tiểu trình, bỏ qua.

o Nếu là cửa sổ ẩn, bỏ qua.

o Nếu là cửa sổ không có tiêu đề, bỏ qua.

o Nếu là cửa sổ Program Manager, bỏ qua.

o Nếu là cửa sổ đang chạy của người dùng (thỏa các điều kiện lọc), lưu lại tên.

Hàm ListWindows:

Chức năng : hàm gọi ngược thực hiện các công việc trên.

BOOL CALLBACK CTaskMgr::ListWindows(HWND hwnd, LPARAM lParam)

Ý nghĩa tham số và giá trị trả về: giống mô tả của hàm gọi ngược nêu ở trên.

Ở đây, tham số lParam là con trỏ trỏ đến cấu trúc WIN_TEXT_LIST do ta tự định

nghĩa để lưu lại tên các ứng dụng:

113

typedef struct {

HWND hWnd; //cua so ma ham CALLBACK thuoc ve

CStringArray sarWinText; //array luu window title

} WIN_TEXT_LIST;

Ý nghĩa cấu trúc khá đơn giản, như đã ghi trong phần chú thích của cấu trúc.

Đến đây, mục tiêu để ra đã hoàn tất, ta có thể tùy nghi sử dụng danh sách vào các

mục đích khác nhau, như bật và tắt ứng dụng đang chạy.

3.3.4 Tắt một ứng dụng đang chạy:

Việc tắt một ứng dụng đang chạy không khó nếu tắt biết rằng ta cần tắt cửa

sổ nào. Điều này nghe có vẻ quá hiển nhiên, ta có thể nói rằng “Tôi biết chứ ! Tôi

cần tắt cửa sổ này, tên cửa sổ đó là…”, nhưng đối với hệ điều hành Windows tên

cửa sổ không có một ý nghĩa gì cả. Điều hệ điều hành cần đó là handle của cửa sổ.

Do vậy ta sẽ viết một hàm đóng cửa sổ khi biết tên cửa sổ. Sau đó, mọi việc còn lại

quá đơn giản:

CWnd* wnd = CWnd::FromHandle(handle);

wnd->PostMessage(WM_CLOSE);

Ta chỉ làm cửa sổ tự gởi một thông điệp WM_CLOSE cho chính nó. Sau đó,

cửa sổ sẽ đóng. Ta không quá lo lắng việc đóng có thành công hay không vì đây

thông thường chỉ là các cửa sổ ứng dụng của người dùng, ngoài ra, nếu cửa sổ có

chứa dữ liệu mà người dùng chưa lưu (chẳng hạn, ta cần đóng cửa sổ Winword mà

người dùng đang gõ văn bản…) hệ điều hành Windows sẽ thông báo hỏi người

dùng. Người dùng có thể chọn không đóng cửa sổ. Khi ấy, ta sẽ yêu cầu đóng cửa

sổ vào lúc thích hợp khác.

Hàm CloseWindow

Chức năng: đóng cửa sổ khi biết tên của nó.

BOOL CTaskMgr::CloseWindow(LPCTSTR sWinTitle)

Hàm CloseWindow sẽ làm các công việc :

114

o Lấy handle cửa sổ desktop. Cửa sổ này là cửa sổ cha của mọi cửa sổ đang

chạy trên màn hình.

o Từ cửa sổ desktop, duyệt qua từng cửa sổ con của desktop.

o Nếu tìm thấy cửa sổ nào có tên phù hợp với cửa sổ ta cần tìm, đóng nó lại.

Hình 3-10 Tắt một ứng dụng đang chạy

3.3.5 Mở một ứng dụng

Việc mở một ứng dụng bằng mã lệnh thực thi không khó nếu ta sử dụng

đúng hàm API do Windows cung cấp. Ở đây, chỉ có điểm lưu ý nhỏ là ứng dụng

chạy nên nêu rõ đường dẫn tuyệt đối. Khi ta sử dụng đường dẫn tương đối, chẳng

hạn “control.exe”, hệ điều hành sẽ dò tìm ứng dụng trong:

(cid:131) Nơi chứa chương trình ứng dụng

(cid:131) Thư mục hiện hành

(cid:131) Thư mục system/system32

(cid:131) Thư mục Windows

(cid:131) Các thư mục liệt kê trong biến môi trường PATH

Vì vậy, có thể ứng dụng không thể được kích hoạt.

Hàm ShellExecute:

115

Chức năng: thực hiện một thao tác (mở, thực thi, tìm kiếm …) một tập tin

hay thư mục.

HINSTANCE ShellExecute(

HWND hwnd,

LPCTSTR lpOperation,

LPCTSTR lpFile,

LPCTSTR lpParameters,

LPCTSTR lpDirectory,

INT nShowCmd

);

Ý nghĩa tham số:

[in]

hwnd : handle cửa sổ gọi.

lpOperation : thao tác lên tập tin:

edit : dùng một trình xử lý văn bản mở tập tin. Nếu lpFile không phải

là một tập tin văn bản, thao tác sẽ thất bại.

explore : mở thư mục lpFile.

find : tìm kiếm trên thư mục lpFile.

open : mở tập tin lpFile. lpFile có thể là một tập tin thực thi, văn bản,

hay thư mục.

print: in tập tin lpFile. Nếu lpFile không phải là một tập tin văn bản,

thao tác sẽ thất bại.

NULL : Các phiên bản trước Windows 2000: tên thao tác mặc định

quy định trong registry. Nếu không, thao tác “open” sẽ được dùng.

Các phiên bản từ Windows 2000: tên thao tác mặc định quy

định trong registry. Nếu không, thao tác “open” sẽ được dùng. Nếu vẫn không

được, hệ điều hành sẽ dùng thao tác đầu tiên đăng ký vào danh sách trong registry.

lpFile: tên tập tin hay thư mục.

116

lpParameters : tham số dành cho lpFile nếu lpFile là một tập tin thực thi.

Nếu lpFile là một tập tin văn bản, lpParameters nên đặt là NULL.

lpDirectory : đường dẫn tuyệt đối.

nShowCmd :

SW_HIDE

Giấu cửa sổ.

SW_MAXIMIZE

Phóng to hết cỡ cửa sổ.

SW_MINIMIZE

Thu nhỏ cửa sổ.

SW_RESTORE

Phục hồi cửa sổ về kích thước mặc định của nó.

SW_SHOW

Hiện cửa sổ theo kích thước mặc định của nó.

SW_SHOWDEFAULT

Đặt trạng thái mặc định của cửa sổ khi mở là hiện ra.

SW_SHOWMAXIMIZED

Hiện và phóng to hết cỡ cửa sổ.

SW_SHOWMINIMIZED

Hiện và thu nhỏ cửa sổ.

SW_SHOWMINNOACTIVE

Thu nhỏ cửa sổ nhưng không kích hoạt nó.

SW_SHOWNA

Hiện cửa sổ như trạng thái mà nó đã quy định.

SW_SHOWNOACTIVATE

Hiện cửa sổ nhưng không kích hoạt nó.

SW_SHOWNORMAL

Hiện và kích hoạt cửa sổ.

Giá trị trả về:

117

[out]

Nếu thành công, trả về giá trị lớn hơn 32.

Nếu thất bại, trả lỗi.

Áp dụng vào chương trình:

(int)ShellExecute(NULL, "open", lpFile, lpParam, lpPath, SW_SHOW);

Với lpFile, lpParam, lpPath lần lượt là các giá trị lpFile, lpParameters,

lpDirectory đã giải thích ở trên. Lưu ý rằng, ta phải ép kiểu “(int)” khi lấy kết quả vì

nguyên hàm của hàm có trị trả về là HINSTANCE. Thực chất, kiểu trị trả về như

thế để tương thích ngược với các ứng dụng 16-bit cũ.

Hình 3-11 Mở một ứng dụng

3.4 Điều khiển máy tính từ xa:

Trong quá trình thực hiện phần mềm, có một yêu cầu quản trị hệ thống là

người quản trị cần log out, restart và shutdown một máy tính hoặc các máy đang

hoạt động. Điều này có thể thực hiện thông qua các hàm API hệ thống của

Windows nhưng trước hết, ta cần phải biết thêm cơ chế đăng nhập của hệ điều hành

Windows.

118

3.4.1 Cơ chế đăng nhập:

3.4.1.1 Winlogon:

Cơ chế đăng nhập của Windows, Winlogon được thiết kế theo mô hình đăng

nhập tương tác gồm 3 phần : thành phần thực thi (“winlogon.exe”), thư viện liên kết

động “Chứng thực và nhận dạng theo cơ chế đồ họa” (Graphical Identification and

Authentication GINA) (“msgina.dll”), và các thành phần mạng. Để biết thêm về

GINA, xem Phụ lục GINA stub – kỹ thuật xây dựng.

Quá trình đăng nhập được mô tả như sau:

Người dùng đăng nhập hệ thống Người dùng sử dụng tài nguyên hệ thống Hệ thống cấp một thẻ bài truy cập (access token) cho người dùng

Dựa vào thẻ bài, hệ thống quyết định xem người dùng có được sử dụng tài nguyên hay không.

Người dùng thóat khỏi hệ thống Hệ thống chấp nhận và hủy thẻ bài

Hình 3-12 Quá trình đăng nhập

* thẻ bài truy cập (access token):

Một thẻ bài truy cập chứa đựng thông tin bảo mật của session đăng nhập. Hệ

thống tạo thẻ bài khi người dùng đăng nhập, và mỗi tiến trình thực thi dưới quyền

của người dùng đều có một bản sao của thẻ bài. Thẻ bài xác định người dùng, nhóm

người dùng và đặc quyền của người dùng. Hệ thống dùng thẻ bài để kiểm soát việc

truy cập đến các đối tượng bảo mật và khống chế các hoạt động liên quan đến hệ

119

thống của người dùng. Tùy thuộc vào đặc quyền của người dùng, mà mức độ khống

chế cao hay thấp. Chẳng hạn, quản trị viên có toàn quyền đối với hệ thống.

3.4.1.2 Phân tích:

• Lấy thẻ bài của người dùng.

• Với thẻ bài, kiểm tra xem người dùng có đặc quyền log out, restart,

Vậy việc ta phải làm là :

• Nếu có, bật đặc quyền lên (cho phép các tiến trình sử dụng đặc quyền để

shutdown hay không.

• Nếu thành công. công việc hoàn tất.

thực hiện thao tác log out, restart, hay shutdown trên hệ thống).

3.4.2 Các hàm API hệ thống được sử dụng:

3.4.2.1 OpenProcessToken

Chức năng : mở thẻ bài truy cập của tiến trình. khi biết handle.

BOOL OpenProcessToken(

HANDLE ProcessHandle,

DWORD DesiredAccess,

PHANDLE TokenHandle

);

Ý nghĩa tham số:

[in]

ProcessHandle : handle của tiến trình.

DesiredAccess : quyền truy cập yêu cầu.

[out]

TokenHandle : handle của thẻ bài.

Giá trị trả về:

[out]

Nếu thành công, trả về khác 0.

120

Nếu thất bại, trả về 0. Gọi GetLastError để biết lỗi.

3.4.2.2 LookupPrivilegeValue

Chức năng : lấy số định dạng cục bộ duy nhất (LUID). LUID là một giá trị

64 bit có ý nghĩa duy nhất trên hệ điều hành mà phát sinh ra số cho đến khi hệ thống

khởi động lại.

BOOL LookupPrivilegeValue(

LPCTSTR lpSystemName,

LPCTSTR lpName,

PLUID lpLuid

);

Ý nghĩa tham số:

lpSystemName : tên hệ thống mà đặc quyền sẽ được lấy.

lpName : tên đặc quyền.

[out]

lpLuid : LUID của hệ thống.

Giá trị trả về

[out]

Nếu thành công, trả về khác 0.

Nếu thất bại, trả về 0. Để biết lỗi, gọi GetLastError.

3.4.2.3 AdjustTokenPrivileges

Chức năng: bật hay tắt đặc quyền của một thẻ bài truy cập, phải có truy cập

TOKEN_ADJUST_PRIVILEGES.

BOOL AdjustTokenPrivileges(

HANDLE TokenHandle,

BOOL DisableAllPrivileges,

PTOKEN_PRIVILEGES NewState,

DWORD BufferLength,

PTOKEN_PRIVILEGES PreviousState,

121

PDWORD ReturnLength

);

Ý nghĩa tham số:

[in]

TokenHandle : handle của thẻ bài cần bật/tắt đặc quyền.

DisableAllPrivileges : TRUE, tắt tất cả các đặc quyền.

FALSE, chỉnh sửa các đặc quyền dựa trên thông tin của NewState.

NewState : trỏ đến cấu trúc TOKEN_PRIVILEGES:

typedef struct _TOKEN_PRIVILEGES {

DWORD PrivilegeCount; // số đặc quyền

LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; // mảng các

LUID

} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;

trong đó cấu trúc LUID_AND_ATTRIBUTES :

typedef struct _LUID_AND_ATTRIBUTES {

LUID Luid; // số LUID

DWORD Attributes.; // thuộc tính của LUID

} LUID_AND_ATTRIBUTES,

*PLUID_AND_ATTRIBUTES

với Attributes tổ hợp các giá trị sau:

Giá trị

Ý nghĩa

SE_PRIVILEGE_ENABLED Đặc quyền bật.

SE_PRIVILEGE_REMOVED Gở bỏ đặc quyền.

None Tắt đặc quyền.

Bảng 3-3 Giá trị của biến Attributes

BufferLength : kích thước theo byte của vùng đệm chứa PreviousState. Giá

trị này là 0 nếu PreviousState là NULL.

122

PreviousState : tương tự NewState, nhưng cho biết trạng thái trước của đặc

quyền cần chỉnh sửa.

ReturnLength : trả về kích thước thật của vùng đệm chứa PreviousState.

NULL nếu PreviousState là NULL.

Giá trị trả về:

[out]

Nếu thành công, trả về khác 0

Nếu thất bại, trả về 0. Gọi GetLastError để biết lỗi.

3.4.2.4 ExitWindowsEx

Chức năng : thực hiện log out, restart, shutdown.

BOOL ExitWindowsEx(

UINT uFlags,

DWORD dwReason

);

Ý nghĩa tham số:

[in]

uFlags: cờ hiệu, là tổ hợp những giá trị sau:

Giá trị Ý nghĩa

Đóng tất cả các cửa sổ và đăng xuất EWX_LOGOFF người dùng

Shutdown hệ thống và tắt máy. Hệ

thống phải hỗ trợ tính năng tắt máy. EWX_POWEROFF Tiến trình gọi phải có đặc quyền

SE_SHUTDOWN_NAME.

Shutdown hệ thống và khởi động lại

EWX_REBOOT máy. Tiến trình gọi phải có đặc quyền

SE_SHUTDOWN_NAME.

123

Shutdown hệ thống ở thời điểm an

toàn nhưng không tắt máy. Tiến trình EWX_SHUTDOWN gọi phải có đặc quyền

SE_SHUTDOWN_NAME.

Bảng 3-4 Giá trị cờ hiệu

Tham số tùy chọn :

Giá trị Ý nghĩa

Ép các tiến trình kết thúc. Cờ hiệu

này có thể làm ứng dụng mất dữ liệu.

EWX_FORCE Windows XP: Nếu máy bị khóa và

cờ không đặct, tiến trình shutdown sẽ

thất bại.

Ép các tiến trình kết thúc nếu chúng

bỏ qua thông điệp yêu cầu kết thúc

thông thường

WM_QUERYENDSESSION hay

EWX_FORCEIFHUNG WM_ENDSESSION. cờ sẽ bỏ qua

nếu đã có EWX_FORCE.

Windows NT and

Windows Me/98/95: không hỗ trợ.

Bảng 3-5 Giá trị cờ hiệu tùy chọn

dwReason: lý do shutdown, xem thêm trong MSDN để biết chi tiết.

Giá trị trả về:

[out]

Nếu thành công, trả về khác 0. Tuy thế, điều này vẫn không chắc rằng thao

tác có thành công hay không.

124

Nếu thất bại, trả về 0. Gọi GetLastError để biết lỗi.

3.4.3 Cài đặt :

Áp dụng các hàm API trên để thực hiện các công việc đề ra ở 3.4.1.2 Phân

tích:

BOOL CShutdownClient::ShutdownSystem(int iOption)

Hàm có tác dụng thực hiện shutdown, restart, log out trong một khoảng thời

gian xác định.

Có một lưu ý nhỏ là trong quá trình làm phần mềm, ta gặp rắc rối là khi thực

thi thành công hàm ShutdownSystem, ta vẫn không chắc là thao tác ta yêu cầu

trên máy khách có thành công hay không. Vì vậy, bên phía Server chỉ biết được

điều này khi Server mất liên lạc với chương trình bên Client. Việc còn lại là ta chỉ

cần thông báo cho Server biết lỗi thực thi không thành công chứ không bao giờ gởi

báo thành công.

Hình 3-13 Điều khiển hoạt động máy tính từ xa

125

3.5 Tương tác hệ thống – Điều khiển các dịch vụ có trên hệ

thống:

Trong quá trình thực hiện phần mềm, có một yêu cầu quản trị hệ thống là

người quản trị muốn biết tại thời điểm hiện tại, máy khách đang hoạt động những

dịch vụ (service) gì. Người quản trị có thể xem danh sách các dịch vụ đó, đồng thời

có thể thay đổi bằng cách thêm (mở một dịch vụ mới), bớt (tắt một dịch vụ đang

chạy). Yêu cầu này đòi hỏi cần phải tìm hiểu cơ chế quản lý dịch vụ trong hệ điều

hành Windows.

3.5.1 Dịch vụ

3.5.1.1 Khái niệm:

Ứng dụng có khả năng hoạt động trong một khỏang thời gian dài trong một

session của hệ điều hành Windows được gọi là dịch vụ. Các dịch vụ có thể tự động

chạy lên mỗi khi máy khởi động, có thể dừng và khởi động lại, và không đưa ra

giao diện với người dùng. Dịch vụ thường được sử dụng trên server hoặc bất cứ

máy nào cần các tính năng hoạt động lâu dài nhưng không cần can thiệp bởi người

dùng.

3.5.1.2 Loại dịch vụ:

Ta không đi quá sâu vào các dịch vụ cấp thấp. Ta chỉ quan tâm các dịch vụ

dạng ứng dụng chạy là 2 loại Win32OwnProcess và Win32ShareProcess.

3.5.1.3 Vòng đời của dịch vụ:

Một dịch vụ trải qua nhiều trạng thái trong vòng đời hoạt động của nó. Trước

hết, dịch vụ được cài đặt trong hệ thống mà nó sẽ chạy. Quá trình này thực thi bộ

cài đặt của dịch vụ và nạp dịch vụ vào trong Service Control Manager (Bộ Quản lý

Điều khiển Dịch vụ). Service Control Manager là một công cụ do hệ điều hành

Windows cung cấp để quản trị các dịch vụ.

126

Sau khi dịch vụ được nạp, nó phải được khởi động (start). Khởi động dịch vụ

cho phép nó hoạt động. Một dịch vụ đang hoạt động (running) có thể tồn tại ở trạng

thái này cho đến khi nó được ngưng lại (stop) hoặc dừng hẳn (pause) hay máy

shutdown. Dịch vụ có thể tồn tại dưới 3 trạng thái căn bản : Đang hoạt động

(Running), Ngưng (Paused), hay Dừng (Stopped). Dịch vụ còn báo về các trạng thái

chuyển (pending) của nó: Tiếp tục Chuyển (ContinuePending), Chuyển Ngưng

(PausePending), Chuyển Khởi động (StartPending), hay Chuyển Dừng

(StopPending). Các trạng thái chuyển cho biết lệnh nào mới vừa được kích hoạt,

nhưng chưa thực thi xong.

Ngoài ra, dịch vụ cần thêm thông tin về trạng thái khởi động của nó. Một số

dịch vụ rất cần thiết cho hệ thống (như dịch vụ DHCP), còn một số thì không.

Người sử dụng máy có thể cần kích hoạt tự động (Automatic), kích hoạt bằng tay

(Manual), hay vô hiệu hóa (Disabled) dịch vụ. Vì vậy, dịch vụ có 3 trạng thái khởi

động (trạng thái dịch vụ khi máy vừa khởi động xong) là Tự động (Automatic),

Bằng tay (Manual), Vô hiệu (Disabled).

Việc điều khiển các dịch vụ đang hoạt động chính là xem danh sách các dịch

vụ, thay đổi 3 trạng thái hoạt động là Đang hoạt động (Running), Ngưng (Paused),

hay Dừng (Stopped), và 3 trạng thái khởi động là : Tự động (Automatic), Bằng tay

(Manual), Vô hiệu (Disabled). Tuy nhiên, với yêu cầu ở đầu mục, ta chỉ cần điều

khiển 2 trạng thái hoạt động là Running và Stopped, và 3 trạng thái khởi động đã

nêu là đủ.

3.5.2 Điều khiển các dịch vụ đang hoạt động trên hệ thống:

Qua kiến thức khái quát về dịch vụ ở 3.5.1, ta có thể thấy rằng để truy xuất

đến các dịch vụ đang chạy trên hệ thống, ta phải thông qua Service Control

Manager. Đây là cách chung nhất, và có vẻ là cách khả thi duy nhất trên Visual C++

do VC++ 6.0 không hỗ trợ về truy xuất liên quan đến dịch vụ.

127

3.5.2.1 Các hàm API sử dụng :

3.5.2.1.1 OpenSCManager:

Chức năng : thiết lập kết nối đến Service Control Manager trên máy tính và

mở cơ sở dữ liệu của Service Control Manager.

SC_HANDLE OpenSCManager(

LPCTSTR lpMachineName,

LPCTSTR lpDatabaseName,

DWORD dwDesiredAccess

);

Ý nghĩa tham sô:

[in]

lpMachineName : tên máy tính. Nếu là NULL, sẽ mở chính máy tính cục

bộ này.

lpDatabaseName : tên của cơ sở dữ liệu Service Control Manager cần được

mở.

dwDesiredAccess : quyền truy cập mong muốn, xem chi tiết trong MSDN

về các quyền truy cập.

Giá trị trả về:

[out]

Nếu thành công, trả về handle của cơ sở dữ liệu Service Control Manager

được mở.

Nếu thất bại, trả về NULL. . Để biết lỗi, gọi GetLastError.

3.5.2.1.2 EnumServicesStatus

Chức năng: đếm và lấy thông tin về các dịch vụ trong một cơ sở dữ liệu

Service Control Manager được mở.

BOOL EnumServicesStatus(

SC_HANDLE hSCManager,

DWORD dwServiceType,

128

DWORD dwServiceState,

LPENUM_SERVICE_STATUS lpServices,

DWORD cbBufSize,

LPDWORD pcbBytesNeeded,

LPDWORD lpServicesReturned,

LPDWORD

);

Ý nghĩa tham số:

[in]

hSCManager: handle của cơ sở dữ liệu Service Control Manager

được mở, do OpenSCManager trả về khi mở thành công.

dwServiceType : loại dịch vụ cần mở

dwServiceState : trạng thái loại dịch vụ cần liệt kê

[out]

lpServices : trỏ đến cấu trúc ENUM_SERVICE_STATUS chứa thông tin

dịch vụ:

typedef struct _ENUM_SERVICE_STATUS {

LPTSTR lpServiceName; // tên đăng ký của dịch vụ

LPTSTR lpDisplayName; //tên của dịch vụ

SERVICE_STATUS ServiceStatus;

} ENUM_SERVICE_STATUS,

*LPENUM_SERVICE_STATUS;

ServiceStatus : là cấu trúc SERVICE_STATUS

typedef struct _SERVICE_STATUS {

DWORD dwServiceType;

DWORD dwCurrentState;

DWORD dwControlsAccepted;

DWORD dwWin32ExitCode;

DWORD dwServiceSpecificExitCode;

129

DWORD dwCheckPoint;

DWORD dwWaitHint;

} SERVICE_STATUS, *LPSERVICE_STATUS;

dwServiceType : loại dịch vụ.

dwCurrentState :

Giá trị Ý nghĩa

SERVICE_CONTINUE_PENDING Tiếp tục chuyển.

SERVICE_PAUSE_PENDING Chuyển ngưng.

SERVICE_PAUSED Dịch vụ ngưng.

SERVICE_RUNNING Dịch vụ đang chạy.

SERVICE_START_PENDING Dịch vụ đang khởi động.

SERVICE_STOP_PENDING Dịch vụ đang dừng.

SERVICE_STOPPED Dịch vụ dừng hẳn.

Bảng 3-6 Tình trạng hiện tại

dwControlsAccepted

Mã điều khiển Ý nghĩa

Dịch vụ là một thành phần mạng

chấp nhận thay đổi trong SERVICE_ACCEPT_NETBINDCHANGE binding mà không cần dừng hay

khởi động lại.

Dịch vụ có thể đọc lại các tham

SERVICE_ACCEPT_PARAMCHANGE số khởi tạo mà không cần dừng

hay khởi động lại.

Dịch vụ có thể ngưng hay tiếp SERVICE_ACCEPT_PAUSE_CONTINUE tục.

SERVICE_ACCEPT_SHUTDOWN Dịch vụ được thông báo khi hệ

130

thống shutdown.

SERVICE_ACCEPT_STOP Dịch vụ có thể dừng.

Bảng 3-7 Loại điều khiển chấp nhận

dwWin32ExitCode : mã lỗi khi có một lỗi xảy ra khi đang khởi động

hay đang dừng.

dwServiceSpecificExitCode : lỗi thực thi do dịch vụ tự định nghĩa.

dwCheckPoint : giá trị tăng dần khi dịch vụ trải qua lần lược các quá

trình khởi động, dừng, ngưng, hay tiếp tục.

dwWaitHint : thời gian dự đoán cho một thao tác khởi động, dừng,

ngưng, hay tiếp tục, tính theo mili giây.

cbBufSize : vùng đệm chứa thông tin dịch vụ từ lpServices.

[out]

pcbBytesNeeded : số byte cần thêm để lấy các mục dịch vụ còn sót (không

chứa đủ trong cbBufSize).

lpServicesReturned : số lượng các mục dịch vụ lấy được.

[in, out]

lpResumeHandle : handle bắt đầu của dữ liệu chứa các mục dịch vụ còn sót

lại.

Giá trị trả về:

[out]

Nếu thành công, trả về khác 0.

Nếu thất bại, trả về 0. Để biết lỗi, gọi GetLastError.

3.5.2.1.3 OpenService

Chức năng: mở một dịch vụ có sẵn.

SC_HANDLE OpenService(

SC_HANDLE hSCManager,

LPCTSTR lpServiceName,

DWORD dwDesiredAccess

131

);

Ý nghĩa tham số

[in]

hSCManager : handle của một cơ sở dữ liệu Service Control Manager được

mở. Hàm OpenSCManager trả về handle này.

lpServiceName : tên của service được mở, tên này không dài quá 256 ký tự.

Cơ sở dữ liệu Service Control Manager phân biệc chữ hoa chữ thường, nhưng so

sánh tên của các dịch vụ thì không. Các ký tự “/” và “\” đều không dùng cho tên của

dịch vụ.

dwDesiredAccess : quyền truy cập dịch vụ mong muốn.

Giá trị trả về

[out]

Nếu thành công, trả về handle của dịch vụ được mở.

Nếu thất bại, trả về NULL. Để biết lỗi, gọi GetLastError.

3.5.2.1.4 StartService

Chức năng : kích hoạt một dịch vụ.

BOOL StartService(

SC_HANDLE hService,

DWORD dwNumServiceArgs,

LPCTSTR* lpServiceArgVectors

);

Ý nghĩa tham số:

hService : handle dịch vụ đã mở bằng OpenService hay CreateService, và

phải có quyền truy cập SERVICE_START.

dwNumServiceArgs : số đối số chuỗi truyền cho dịch vụ.

lpServiceArgVectors : mảng các đối số chuỗi. Dịch vụ driver không nhận

các đối số này. Nếu không cần đối số cho dịch vụ, biến đặt là NULL.

Giá trị trả về:

132

[out]

Nếu thành công, trả về khác 0.

Nếu thất bại, trả về 0. Để biết lỗi, gọi GetLastError.

3.5.2.1.5 ControlService

Chức năng : gởi mã điều khiển đến dịch vụ.

BOOL ControlService(

SC_HANDLE hService,

DWORD dwControl,

LPSERVICE_STATUS lpServiceStatus

);

Ý nghĩa tham số:

hService : handle dịch vụ đã mở bằng OpenService hay CreateService, và

phải có quyền truy cập SERVICE_START.

dwControl : mã điều khiển.

lpServiceStatus: trỏ đến cấu trúc SERVICE_STATUS nhận thông tin tình

trạng mới nhất của dịch vụ, xem thêm 3.5.2.12 EnumServicesStatus để biết thêm

về cấu trúc.

Giá trị trả về:

[out]

Nếu thành công, trả về khác 0.

Nếu thất bại, trả về 0. Để biết lỗi, gọi GetLastError.

3.5.2.1.6 ChangeServiceConfig:

Chức năng : thay đổi các tham số cấu hình của dịch vụ.

BOOL ChangeServiceConfig(

SC_HANDLE hService,

DWORD dwServiceType,

DWORD dwStartType,

DWORD dwErrorControl,

133

LPCTSTR lpBinaryPathName,

LPCTSTR lpLoadOrderGroup,

LPDWORD lpdwTagId,

LPCTSTR lpDependencies,

LPCTSTR lpServiceStartName,

LPCTSTR lpPassword,

LPCTSTR lpDisplayName

);

Ý nghĩa tham số

[in]

hService : handle dịch vụ đã mở bằng OpenService hay CreateService

dwServiceType : loại dịch vụ, xem 3.5.2.1.2 EnumServicesStatus để biết

thêm.

dwStartType : loại trạng thái khởi động.

dwErrorControl : lỗi điều khiển, để SERVICE_NO_CHANGE nếu không

muốn thay đổi điều khiển lỗi đang có.

lpBinaryPathName : tên tập tin nhị phân thực thi của dịch vụ.

lpLoadOrderGroup : tên nhóm thứ tự nạp mà dịch vụ là thành viên.

lpdwTagId : giá trị thẻ ghi duy nhất trong nhóm nạp.

lpDependencies : dịch vụ hay nhóm các dịch vụ trong nhóm nạp cần tải

trước khi dịch vụ có thể khởi động.

lpServiceStartName : tên tài khỏan mà dịch vụ chạy.

lpPassword : mật khẩu.

lpDisplayName : tên giao tiếp của dịch vụ với các ứng dụng.

Giá trị trả về:

[out]

Nếu thành công, trả về khác 0.

Nếu thất bại, trả về 0. Để biết lỗi, gọi GetLastError.

3.5.2.1.7 CloseServiceHandle

134

Chức năng : đóng handle được mở cho cơ sở dữ liệu Service Control

Manager hay đối tượng dịch vụ.

BOOL CloseServiceHandle(

SC_HANDLE hSCObject

);

Ý nghĩa tham số:

[in]

hSCObject : handle được mở cho cơ sở dữ liệu Service Control Manager

hay đối tượng dịch vụ cần đóng.

Giá trị trả về:

[out]

Nếu thành công, trả về khác 0.

Nếu thất bại, trả về 0. Để biết lỗi, gọi GetLastError.

3.5.2.2 Cài đặt :

Dựa vào các hàm API nêu ở 3.5.1, ta sẽ thực hiện các cài đặt

3.5.2.2.1 Xem danh sách các dịch vụ :

Các công việc cần làm:

o Mở cơ sở dữ liệu SERVICES_ACTIVE_DATABASE của Service Control

Manager.

o Lấy danh sách các dịch vụ.

o Đóng cơ sở dữ liệu lại.

Hàm cài đặt

BOOL CTaskMgr::GetServiceList(ENUM_SERVICE_STATUS* &pSrvList,

DWORD& nCount)

Có lưu ý cho hàm GetServiceBufferSizeNeeded. Hàm cài đặt này

có tác dụng trả về số byte thực sự cần để lưu các thông tin về các dịch vụ.

135

Hình 3-14 Xem danh sách các dịch vụ

3.5.2.2.2 Đổi trạng thái khởi động của dịch vụ :

Thực hiện các công việc sau:

o Mở cơ sở dữ liệu Service Control Manager.

o Mở dịch vụ

o Thay đổi trạng thái khởi động là SERVICE_AUTO_START hay

SERVICE_DEMAND_START hay SERVICE_DISABLED.

o Đóng các handle lại.

Hàm cài đặt ChangeWaytoStartup

int CTaskMgr::ChangeWaytoStartup(CString sServiceName, DWORD

dwStartType)

136

Hình 3-15 Đổi trạng thái khởi động

3.5.2.2.3 Khởi động dịch vụ:

Thực hiện các công việc sau:

o Mở cơ sở dữ liệu Service Control Manager.

o Mở dịch vụ

o Khởi động dịch vụ.

o Đóng các handle lại.

Hàm cài đặt StartService

int CTaskMgr::StartService(CString sServiceName)

3.5.2.2.4 Dừng dịch vụ:

Thực hiện các công việc sau:

o Mở cơ sở dữ liệu Service Control Manager.

o Mở dịch vụ

o Dừng dịch vụ.

o Đóng các handle lại.

Hàm cài đặt StopService

int CTaskMgr::StopService(LPCTSTR sServiceName)

137

Hình 3-16 Khởi động / tắt dịch vụ

Hoàn tất yêu cầu ban đầu.

Chương 4 Các công nghệ :

Trong ba công nghệ truyền hình ảnh, âm thanh chúng em đã nghiên cứu và

trình bày trong chương này đều có những ưu và nhược điểm riêng:

RFB H323 Windows Media

Encoder (WME)

Khả năng ứng dụng Là một bộ phát Ưu điểm Giải quyết triệt để

rộng rãi trên nhiều hệ triển phần mềm của vấn đề quan sát màn

điều hành khác nhau. Windows, WME hình từ xa vì nghi

Với khả năng tích hợp tích hợp chặt chẽ thức giao tiếp với

mạnh mẽ, H323 có thể với hệ điều hành hai đầu cuối là là

hỗ trợ nhiều công nghệ Windows, đưa ra vùng đệm khung cho

các khả năng mã màn hình. Nghi thức truyền hình ảnh âm

hóa và giải mã âm mã nguồn mở, hỗ trợ thanh khác nhau

thanh hình ảnh theo đa nền. (H261, H263…). Công

dòng rất hiệu quả. nghệ mã nguồn mở.

Khuyết điểm Khả năng ứng dụng Các bản phát hành trên Đòi hỏi tối đa việc

các lĩnh vực khác Windows còn nhiều hỗ trợ về hệ điều

138

hành trong việc hạn chế và lỗi, chưa khá hạn chế, nghi

truyền gởi (phải là giải quyết triệt để việc thức hầu như chỉ

hệ điều hành hỗ trợ trên Windows dành riêng cho ứng

Windows các phiên (còn “bóng dáng” của dụng điều khiển máy

bản mới thì hỗ trợ Linux trong việc biên tính từ xa.

hiệu quả cho dịch).

WME).

Bảng 4-1 So sánh các công nghệ nghiên cứu

Qua các sơ lược về ưu khuyết điểm trên, chúng em chọn nghi thức RFB để

thực hiện việc cài đặt, hai công nghệ còn lại chỉ dừng ở mức tìm hiểu và nghiên

cứu.

4.1 RFB

4.1.1 Giới thiệu:

RFB (“remote framebuffer”) là một nghi thức đơn giản để truy xuất đến giao

diện người dùng đồ họa. Vì nó làm việc ở mức vùng đệm khung, nghi thức

tương thích với mọi ứng dụng và hệ thống theo dạng “cửa sổ”, gồm cả X11,

Window.

Đầu cuối ở xa là nơi người dùng sử dụng (chẳng hạn màn hình kèm bàn

phím và có hay không chuột) được gọi là RFB client. Đầu cuối nơi những thay

đổi trên vùng đệm khung phát sinh (chẳng hạn các ứng dụng và hệ thống dạng

“cửa sổ”) gọi là RFB server.

139

Hình 4-1 Giới thiệu nghi thức RFB

RFB là nghi thức dành cho thin client. Điều đáng lưu ý trong thiết kế nghi

thức RFB là có rất ít yêu cầu về hệ thống cho client. Do đó, client có thể chạy

trên hầu hết các loại phần cứng khác nhau, công việc cài đặt, xây dựng client

càng đơn giản càng tốt.

Nghi thức xây dựng cho client ở dạng stateless. Nếu nghi thức ngắt kết nối từ

một server cho trước và sau đó kết nối lại với server, trạng thái của giao diện

người dùng được giữ nguyên. Hơn nữa, một đầu cuối client khác cũng có thể kết

nối vào cùng RFB server. Ở đầu cuối mới, người dùng cũng sẽ thấy chính xác

cùng một giao diện người dùng đồ họa như đầu cuối kia. Khi có kết nối mạng

thích hợp, người dùng có thể truy cập, các ứng dụng cá nhân của họ, và trạng

thái của ứng dụng đó sẽ giữ gìn giữa các truy xuất từ các vị trí khác nhau. Điều

này cung cấp cho người dùng một cách nhìn thân thiện, chuẩn mực về kiến trúc

máy tính khi họ đi đến bất cứ đâu.

4.1.2 Nghi thức xuất ra màn hình:

Phần xuất của nghi thức dựa trên nguyên tắc đồ họa đơn nhất : “in một hình

chữ nhật dữ liệu điểm ảnh (pixel) tại một vị trí x, y cho trước”. Nhìn sơ qua,

điều này có vẻ không phải là cách làm hiệu quả để vẽ nhiều thành phần giao

diện người dùng. Tuy nhiên, áp dụng nhiều thuật tóan mã hóa khác nhau cho dữ

liệu điểm ảnh lại đem đến cho chúng ta sự linh động rất cao trong việc điều

140

chỉnh các thông sô như băng thông mạng, tốc độ vẽ bên client và tốc độ xử lý

của server.

Một lọat các hình chữ nhật như trên tạo nên một cập nhật vùng đệm khung

(hay đơn giản là một cập nhật). Một cập nhật đại diện cho sự thay đổi từ trạng

thái của một vùng đệm khung hiệu lực sang trạng thái khác, do vậy trong một

khía cạnh nào đó nó khá giống với khung hình của video. Các hình chữ nhật

trong một cập nhật thông thường rời rạc nhưng điều này cũng không đáng lưu ý

lắm.

Nghi thức cập nhật được điều khiển bởi người dùng. Có nghĩa là, một cập

nhật chỉ gởi từ một server đến một client để đáp ứng một yêu cầu rõ ràng từ phía

người dùng. Điều này cho phép nghi thức có thay đổi tùy nghi về chất lượng

truyền. Client và đường mạng càng chậm, tần suất cập nhật càng thấp. Với các

ứng dụng điển hình, những thay đổi trên cùng một vùng của vùng đệm khung

thường có khynh hướng xảy ra ngay lần lượt. Với một client chậm và/hay một

đường mạng chậm, các trạng thái thay đổi nhanh có thể bỏ qua, đưa đến kết quả

là có ít lưu thông mạng hơn và có ít đường vẽ trên client hơn.

4.1.3 Nghi thức nhập thông tin:

Phần nhập của nghi thức dựa trên mô hình máy trạm chuẩn gồm một bàn

phím và một thiết bị trỏ đa nút (thông thường là chuột). Các sự kiện nhập chỉ

đơn giản gởi cho server từ client khi người dùng nhấn phím hoặc nút trỏ, hay bất

cứ khi nào thiết bị trỏ di chuyển. Các sự kiện đầu vào cũng có thể tổng hợp từ

các thiết bị nhập/xuất không chuẩn. Ví dụ, một dụng cụ nhận dạng chữ viết tay

dạng cây viết có thể phát sinh các sự kiện bàn phím.

4.1.4 Trình bày dữ liệu điểm ảnh:

Giao tiếp ban đầu của RFB client và server liên quan đến một quá trình thỏa

thuận về định dạng và mã hóa cho dữ liệu điểm ảnh sẽ gởi. Quá trình thỏa thuận

này được thiết kế nhằm mục đích cho họat động xử lý ở client càng dễ dàng

càng tốt. Điều lưu ý là server phải luôn có thể đáp ứng mọi định dạng mà người

141

dùng mong muốn. Tuy nhiên client có thể tùy nghi với nhiều dạng và mã hóa

khác nhau, nó có thể chọn dạng mà dễ dàng cho server xử lý hơn.

Định dạng điểm ảnh là việc trình bày các màu riêng biệt của các giá trị điểm

ảnh. Định dạng điểm ảnh phổ biến nhất là 24-bit và 16-bit “màu thực”, mà trong

các trường bit giá trị điểm ảnh biên dịch trực tiếp thành các cường độ của sắc

đỏ, xanh lá cây và xanh da trời, và 8-bit “bản màu” nơi một quá trình ánh xạ tùy

ý có thể dùng để biên dịch các giá trị điểm ảnh sang các cường độ RGB (Red

Green Blue).

Mã hóa là việc làm thế nào một chữ nhật dữ liệu điểm ảnh sẽ gởi trên đường

truyền. Mỗi chữ nhật dữ liệu điểm ảnh được đính trước bằng một header cho

biết vị trí X, Y của hình chữ nhật trên màn hình, bề rộng và chiều cao của hình

chữ nhật, và loại mã hóa xác định dạng mã hóa của dữ liệu điểm ảnh. Dữ liệu

theo đó sẽ dùng đúng loại mã hóa đã xác định.

4.1.5 Các mở rộng cho nghi thức:

Nghi thức có thể mở rộng bằng việc thêm các loại mã hóa mới. Các loại mã

hóa được định nghĩa hịên tại là Raw, CopyRect, RRE, CoRRE, Hextile và ZRLE.

Trong thực tế, chúng ta chỉ dùng ZRLE, Hextile và CopyRect vì chúng cung cấp

khả năng nén tốt nhất cho một máy tính điển hình.

Thêm vào các mã hóa thật, client có thể yêu cầu một “mã hóa giả” để khai

báo với server rằng nó có hỗ trợ một mở rộng của nghi thức. Một server không

hỗ trợ phần mở rộng sẽ bỏ qua mã hóa giả trên. Chú ý rằng điều này có nghĩa là

client phải ngầm hiểu là server không hỗ trợ phần mở rộng cho đến khi nó nhận

được xác nhận về mở rộng đó của server.

Điều quan trọng là loại mã hóa và mã hóa giả khác không gây xung đột. Để

tránh điều đó, phiển bản nghi thức RFB và các loại mã hóa được RealVNC Ltd

chứng thực và duy trì.

142

4.1.6 Các thông điệp nghi thức:

Nghi thức RFB có thể họat động trên mọi tầng vận chuyển tin cậy, dựa trên

luồng byte hay thông điệp. Có hai phần trong nghi thức, một pha bắt tay khởi

tạo theo sau một giao tiếp nghi thức thông thường.

Bắt tay khởi tạo bao gồm các thông điệp về Phiên bản Nghi thức, Bảo mật,

Khởi tạo bên Client và Khởi tạo bên Server, sẽ được mô tả sau. Chú ý cả server

và client đều gởi thông điệp Phiên bản Nghi thức.

Nghi thức tiến hành trong phần giao tiếp thông thường sau thông điệp Khởi

tạo bên Server. Ở phần này, client có thể gởi bất cứ thông điệp nào mà nó muốn,

và có thể nhận được những thông điệp kết quả từ server. Mọi thông điệp đó đều

bắt đầu bằng một byte loại thông điệp, theo sau là dữ liệu.

Bảng mô tả thông điệp sau đây sử dụng các dạng dữ liệu cơ bản U8, U16,

U32, S8, S16, S32. Chúng đại diện lần lượt cho dữ liệu số nguyên không dấu 8,

16 và 32 bit và số nguyên có dấu 8, 16, 32 bit. Mọi số nguyên dạng nhiều byte

(không tính giá trị điểm ảnh) đều theo thứ tự lớn trước nhỏ sau (bit càng ở đầu

càng có giá trị).

Kiểu dữ liệu PIXEL được xây dựng hiển thị gía trị điểm ảnh của các byte

dạng byte cho mỗi điểm ảnh (bytePerPixel), trong đó 8x bytePerPixel là số bit

mỗi điểm ảnh (bits-per-pixel) thỏa thuận bởi client và server hoặc trong thông

điệp Khởi tạo bên Server hay thông điệp Đặt Định dạng Điểm ảnh

4.1.6.1 Các thông điệp bắt tay khởi tạo

4.1.6.1.1 ProtocolVersion

Quá trình bắt tay bắt đầu khi server gởi cho client thông điệp

ProtocolVersion. Thông điệp này báo cho client biết số phiên bản nghi thức RFB

cao nhất mà server hỗ trợ. Client sau đó sẽ hồi đáp với một thông điệp tương tự cho

biết số phiên bản nghi thức sẽ dùng (có thể khác với số server đưa). Client không

bao giờ yêu cầu phiên bản nghi thức cao hơn số server nêu. Cả server và client đều

có thể hỗ trợ tương thích ngược bằng cơ chế này.

143

Chỉ những phiên bản nghi thức được phát hành lúc này là 3.3, 3.7 và 3.8

(phiên bản 3.5 thường được hồi trả sai bởi một số client, nhưng thường được server

hiểu là 3.3). Việc thêm các dạng mã hóa và mã hóa giả mới thường không có đòi

hỏi thay đổi trong phiên bản nghi thức, vì server chỉ cần đơn giản bỏ qua dạng mã

hóa nếu nó không hiểu.

Thông điệp ProtocolVersion bao gồm 12 byte là một chuỗi ASCII trong định

dạng “RFB xxx.yyy\n” với xxx và yyy là số phiên bản nghi thức chính và phụ, độn

thêm các số 0.

"RFB 003.003\n" (hex 52 46 42 20 30 30 33 2e 30 30 33 0a)

Số byte Giá trị

12

hay

"RFB 003.007\n" (hex 52 46 42 20 30 30 33 2e 30 30 37 0a)

Số byte Giá trị

12

hay

"RFB 003.008\n" (hex 52 46 42 20 30 30 33 2e 30 30 38 0a)

Số byte Giá trị

12

4.1.6.1.2 Bảo mật

Một khi phiên bản nghi thức thỏa thuận xong, server và client phải thỏa

thuận tiếp dạng bảo mật dùng trong kết nối.

Phiên bản 3.7 tiếp Server lập danh sách các dạng bảo mật nó hỗ trợ:

Số byte Type [Giá Mô tả

trị]

Số các dạng bảo mật U8 1

số các dạng bảo mật Mảng U8 Các dạng bảo mật

Nếu server đưa danh sách có ít nhất một dạng được client hỗ trợ, client gởi

trả một byte đơn cho biết dạng bảo mật nào được dùng khi kết nối :

Số byte Type [Giá Mô tả

trị]

144

1 U8 Dạng bảo mật

Nếu số dạng bảo mật bằng 0, sau đó vì một lý do nào đó kết nối thất bại (e.g

server không thể hỗ trợ phiên bản được yêu cầu). Việc này sẽ tạo ra một chuỗi mô

tả lý do (với số độ dài cho biết chuỗi kèm sau dài bao nhiêu).

Số byte Type [Giá Mô tả

trị]

4 Độ dài chuỗi lý do U32

Độ dài chuỗi Mảng U8 Chuỗi lý do

Server đóng kết nối sau khi gởi chuỗi lý do.

Phiên bản 3.3 tíếp Server quyết định dạng bảo mật và gởi một word đơn:

Số byte Type [Giá Mô tả

trị]

4 Dạng bảo mật U32

Dạng bảo mật chỉ có các giá trị 0, 1 và 2.Giá trị 0 cho biết kết nối thất bại và

gởi kèm theo chuỗi lý do đã được mô tả ở trên.

Dạng bảo mật định nghĩa trong tài liệu này là

Số Tên

0 Thất bại

1 Không có gì

2 Chứng thực VNC

Những dạng bảo mật khác là:

Số Tên

5 RA 2

6 RA 2ne

16 Tight

17 Ultra

18 TLS

145

Một khi dạng bảo mật được quyết định, dữ liệu phù hợp với dạng đó sẽ gởi

kèm (xem 4.3.6.2 để biết thêm chi tiết). Vào cuối pha bắt tay bảo mật, nghi thức

thường được tiếp tục với thông điệp SecurityResult.

Chú ý rằng sau pha bắt tay bảo mật, dữ liệu nghi thức tiếp sẽ được gởi trên

một kênh mã hóa hay đã được thay đổi.

4.1.6.1.3 SecurityResult

Server gởi một word (cid:31)ể thông báo client quá trình bắt tay bảo mật (cid:31)ã thành

công hay chưa.

Số byte Type [Giá Mô tả

trị]

Trạng thái: 4 U32

0 OK

1 thất bại

Nếu thành công, nghi thức tiếp tục với thông điệp ClientInitialisation.

Phiên bản 3.8 tiếp Nếu không thành công, server gởi chuỗi mô tả lý do thất bại, và

sau đó đóng kết nối:

Số byte Type [Giá Mô tả

trị]

4 Độ dài chuỗi lý do U32

Độ dài chuỗi Mảng U8 Chuỗi lý do

Phiên bản 3.3 và 3.7 Nếu không thành công, server đóng kết nối.

4.1.6.1.4 ClientInitialisation

Khi client và server đã vui vẻ sẵn sàng nói chuyện với nhau theo dạng bảo

mật đã thỏa thuận, client gởi một thông điệp khởi tạo:

Số byte Type [Giá Mô tả

trị]

1 U8 cờ chia sẻ

146

Cờ chia sẻ khác 0 nếu server thử cho chia sẻ desktop cho các client khác kết

nối, 0 nếu nó thiết lập một kết nối loại trừ cho client này bằng cách ngắt kết nối

những client khác.

4.1.6.1.5 ServerInitialisation

Sau khi nhận thông điệp ClientInitialisation, server gởi thông điệp

ServerInitialisation. Thông điệp này cho client biết bề dài và bề rộng của vùng đệm

khung, định dạng điểm ảnh và tên của desktop:

Số byte Type [Giá trị] Mô tả

chiều rộng của khung U16 2

chiều dài của khung U16 2

định dạng điểm ảnh PIXEL_FORMAT 16

chiều dài tên U32 4

chuỗi tên mảng U8 chiều dài tên

với PIXEL_FORMAT là

Số byte Type [Giá Mô tả

trị]

số bit mỗi điểm ảnh U8 1

độ sâu màu U8 1

cờ big-endian U8 1

cờ true-color U8 1

red-max U16 2

green-max U16 2

blue-max U16 2

red-shift U8 1

green-shift U8 1

blue-shift U8 1

độn 3

147

Định dạng điểm ảnh bên server là số bit dùng cho mỗi giá trị điểm ảnh trên

đường truyền. Giá trị này phải lớn hơn hay bằng độ sâu màu, là số bit dùng thực

trong giá trị điểm ảnh. Hiện tại số bit điểm ảnh phải là 8, 16 hay 32 – ít hơn 8 bit

màu chưa được hỗ trợ. Cờ big-endian là khác 0 (đúng) nếu những điểm ảnh đa byte

được hiểu theo một big-endian (tức là một số có byte chứa giá trị càng lớn thì càng

ở cuối các byte). Hiển nhiên cờ này vô nghĩa với điểm ảnh 8 bit màu.

Nếu cờ true-color là khác 0 (đúng) nếu sáu thành phần cuối xác định làm thế

nào tách cường độ đỏ, xanh và xanh dương từ giá trị điểm ảnh. Red-max là giá trị đỏ tối đa (=2n – 1 với n là số bit dùng cho màu đỏ). Chú ý giá trị này luôn theo thứ

tự big-endian. Red-shift là số lần cần dời bit để lấy giá trị đỏ trong điểm ảnh cho

đến bit quan trọng nhất. Green-max, green-shift và blue-max, blue-shift tương tự

cho màu xanh lá và xanh dương. Chẳng hạn, để tìm giá trị đỏ (từ 0 đến red-max) từ

một điểm ảnh cho trước, làm như sau:

• Tráo đổi giá trị điểm ảnh dựa theo cờ big-endian (e.g nếu cờ big-endian

là 0 (sai) và thứ tự byte của máy chủ là big endian, tráo đổi).

• Dời bit sang phải theo red-shift.

• AND với red-max (theo thứ tự byte của máy chủ).

Nếu cờ true-color là 0 (sai) thì server sẽ dùng giá trị điểm ảnh mà không trực

tiếp lấy từ cường độ đỏ, xanh lá và xanh dương, nhưng được biểu thị chỉ rõ trong

bản đồ màu. Các mục trong bản đồ màu được server thiết lập dùng thông điệp

SetColourMapEntries (phần 4.3.6.4.2).

4.1.6.2 Các dạng bảo mật

4.1.6.2.1 None

Không cần chứng thực và dữ liệu nghi thức gởi không mã hóa.

Phiên bản 3.8 tiếp Nghi thức tiếp tục với thông điệp SecurityResult.

Phiên bản 3.3 và 3.7 Nghi thức tiếp tục với thông điệp ClientInitialisation.

4.1.6.2.2 Chứng thực VNC

148

Chứng thực VNC được dùng và dữ liệu nghi thức gởi không mã hóa. Server

gởi một giá trị thử 16 byte ngẫu nhiên:

Số byte Type [Giá Mô tả

trị]

U16 thử 16

Client mã hóa giá trị thử với DES, dùng mật mã được người dùng cung cấp

là khóa, và gởi trả hồi đáp 16 byte:

Số byte Type [Giá Mô tả

trị]

U16 hồi đáp 16

Nghi thức tiếp tục với thông điệp SecurityResult.

4.1.6.3 Các thông điệp gởi từ client tới server

4.1.6.3.1 SetPixelFormat

Thiết lập định dạng mà giá trị điểm ảnh sẽ gởi trong những thông điệp

FramebufferUpdate. Nếu client không gởi một thông điệp thì server gởi những giá

trị điểm ảnh trong định dạng mặc nhiên ghi rõ trong thông điệp ServerInitialisation.

(phần 4.3.6.1.5).

Nếu cờ true-color là 0 (sai) thì nó cho bíêt một “bản đồ màu” sẽ được dùng.

Server có thể thiết lập bất cứ mục nào trong bản đồ màu dùng thông điệp

SetColourMapEntries (phần 4.3.6.4.2). Ngay tức khắc sau khi client gởi thông điệp

này (SetPixelFormat) bản đồ màu sẽ bỏ trống, thậm chí nếu đã có những mục được

thiết lập bởi server.

Số byte Type [Giá trị] Mô tả

dạng thông điệp U8 0 1

độn 3

định dạng điểm ảnh PIXEL_FORMAT 16

với PIXEL_FORMAT được mô tả trong 4.3.6.15:

149

Số byte Type [Giá Mô tả

trị]

số bit mỗi điểm ảnh U8 1

độ sâu màu U8 1

cờ big-endian U8 1

cờ true-color U8 1

red-max U16 2

green-max U16 2

blue-max U16 2

red-shift U8 1

green-shift U8 1

blue-shift U8 1

độn 3

4.1.6.3.2 FixColourMapEntries

Thông điệp này không còn được dùng. Trước đây nó là một dạng thông điệp.

4.1.6.3.3 SetEncodings

Thiết lập dạng mã hóa mà dữ liệu điểm ảnh dùng được server gởi. Thứ tự

của các dạng mã hóa được ghi trong thông điệp là chỉ dẫn của client cho biết ý

muốn của nó( mã hóa được ghi trước nhất là dạng mà nó thích hơn cả). Server có

thể hoặc không nghe theo chỉ dẫn này. Dữ liệu điểm ảnh có thể luôn luôn gởi dưới

dạng mã hóa thô (raw) thậm chí khi không có khai báo tường minh.

Thêm vào các mã hóa thật, client có thể yêu cầu các “mã hóa giả’ để khai

báo với server rằng nó hỗ trợ các mở rộng nào đó cho nghi thức. Server mà không

hỗ trợ phần mở rộng sẽ đơn giản bỏ qua mã hóa giả. Chú ý rằng client phải ngầm

định server không hỗ trợ phần mở rộng cho đến khi nó nhận thông tin xác nhận rõ

phần mở rộng từ server.

Xem phần 4.3.6.5 cho định dạng dữ liệu cho mỗi mã hóa và phần 4.3.6.6 cho

định nghĩa các mã hóa giả.

150

Số byte Type [Giá Mô tả

trị]

dạng thông điệp U8 2 1

độn 1

số lượng các mã hóa U16 2

theo sau là các số lượng các mã hóa gởi lặp đi lặp lại :

Số byte Type [Giá Mô tả

trị]

dạng mã hóa U32 4

mã hóa thô (raw) 0

mã hóa CopyRect 1

mã hóa RRE 2

mã hóa CoRRE 4

mã hóa Hextile 5

mã hóa ZRLE 16

mã hóa giả Cursor 0xffffff11

mã hóa giả DesktopSize 0xffffff21

Những mã hóa được đăng kí

khác 6,7,8

zlib, tight, zlibhex 0xffffff00 tới 0xffffff10

0xffffff12 tới 0xffffff20

0xffffff22 tới 0xffffffff

các tùy chọn của tight

4.1.6.3.4 FrameBufferUpdateRequest

Báo cho server biết client quan tâm đến một khu vực trong vùng đệm khung

xác định bằng x-position, y-position, width và height. Server thường hồi đáp

FrameBufferUpdateRequest bằng cách gởi một FramebufferUpdate. Chú ý rằng tuy

151

là như thế một FramebufferUpdate có thể gởi để hồi đáp nhiều

FramebuferUpdateRequest.

Server ngầm định rằng client giữ một bản sao của mọt phần trong vùng đệm

khung mà nó quan tâm. Điều này có nghĩa là server thông thường chỉ cần gởi các

cập nhật tăng dần cho client.

Tuy thế, nếu vì vài nguyên nhân nào đó client đã mất nội dung khu vực nó

cần, thì client có thể gởi một FramebufferUpdateRequest với incremental đặt bằng

0 (sai). Việc này yêu cầu server gởi cả nội dung của cả khu vực càng sớm càng tốt.

Khu vực sẽ không cập nhật khi dùng mã hóa CopyRect.

Nếu client đã không mất nội dung khu vực nó quan tâm, thì nó sẽ gởi một

FramebufferRequest với incremental đặt khác 0 (đúng). Nếu và khi có bất kì sự

thay đổi tới khu vực xác định của vùng đệm khung, server sẽ gởi một

FramebufferUpdate. Chú ý rằng có một chu kỳ bất giữa việc gởi và nhận các

FramebufferUpdateRequest và FramebufferUpdate.

Trong trường hợp là một client nhanh (cấu hình mạnh), client có thể muốn

điều chỉnh tần suất gởi các FramebufferUpdateRequest tăng dần để tránh lấn chiếm

đường mạng.

Số byte Type [Giá Mô tả

trị]

dạng thông điệp U8 1

incremental U8 1

x-position U16 2

y-position U16 2

width U16 2

height U16 2

4.1.6.3.5 Sự kiện phím

152

là khi một phím nhấn hoặc thả. Cờ down là khác 0 (đúng) nếu phím đang

được nhấn, 0 (sai) nếu phím đang thả. Phím tự nó cũng được dùng để xác định giá

trị “keysym” định nghĩa bởi Hệ thống X Windows.

Số byte Type [Giá Mô tả

trị]

dạng thông điệp U8 4 1

cờ down U8 1

độn 2

phím U32 4

Dành cho hầu hết các phím, “keysym” giống với giá trị ASCII tương ứng.

Để biết chi tiết, xem The Xlib Reference Manual, phát hành bởi O’Reilly &

Associates, hay xem file tiêu đề từ bất kỳ một cài đặt của hệ

hống X Windows. Một số phím thông dụng khác:

153

Giá trị keysym Tên phím

0xff08 BackSpace

0xff09 Tab

0xff0d Return hay Enter

0xff1b Escape

0xff63 Insert

0xffff Delete

0xff50 Home

0xff57 End

0xff55 Page Up

0xff56 Page Down

0xff51 Left

0xff52 Up

0xff53 Right

0xff54 Down

Tên phím Giá trị keysym

0xffbe F1

0xffbf F2

0xffc0 F3

0xffc1 F4

… …

0xffc9 F12

0xffe1 Shift (trái)

0xffe2 Shift (phải)

0xffe3 Control (trái)

0xffe4 Control (phải)

0xffe7 Meta (trái)

0xffe8 Meta (phải)

0xffe9 Alt (trái)

0xffea Alt (phải)

154

Việc thông dịch keysym khá phức tạp. Nhằm để hoạt độn phối hợp rộng rãi

càng nhiều càng tốt, cần tuân theo các chỉ dẫn sau:

• “Shift state” (i.e. khi các phím shift được nhấn) chỉ nên dùng như một hướng

dẫn khi biên dịch một keysym. Chẳng hạn, trên một bàng phím US ký tự ‘#’

được nhấn kèm theo shift mới được, còn bàn phím UK thì không. Một server

với một bàn phím US nhận một ký tự ‘#’ từ một client với một bàn phím UK

sẽ không được gởi với bất kỳ phím shift nhấn nào cả. Trong trường hợp đó,

server có thể cần “giả” nhấn shift trên hệ thống cục bộ của nó, nhằm để lấy

ký tự có hay không shift, ví dụ, một ký tự ‘3’.

• Việc phân biệt ký tự chữ hoa chữ thường là rất quan trọng. Điều này không

đúng với một số bàn phím trong các Hệ thống X Windows xử lý giống nhau

với cả chữ hoa chữ thường. Chẳng hạn, server nhận được một keysym ‘A’

hoa mà không kèm theo nhấn shift thì nên thông dịch là một ký tự ‘A’ hoa.

Một lần nữa, điều này cũng có thể cần làm “giả” cục bộ nhấn shift.

• Server nên bỏ qua việc “khóa” các keysym chẳng hạn CapsLock và

NumLock khi có thể. Thay vào đó chúng nên được thông dịch mỗi keysym

dựa vào ký tự tùy theo trường hợp của nó.

• Không giống Shift, trạng thái của các phím tinh chỉnh như Control và Alt

cần phải lấy để chỉnh sửa việc thông dịch các keysym khác. Chú ý rằng sẽ

không có những keysym cho ký tự điều khiển ASCII ví dụ như ctrl-a – các

tổ hợp phím này được phát sinh qua khung nhìn bằng cách gởi một nhấn

Control và một nhấn ‘a’.

• Trên khung nhìn khi các phím tinh chỉnh như Control và Alt có thể cũng

được dùng để phát sinh các keysym dựa trên ký tự, các khung nhìn có thể

cần gởi thêm các sự kiện “thả” nhằm để keysym được thông dịch chính xác.

Chẳng hạn, trên một bàn phím PC Đức, ctrl-alt-q sẽ tạo ra ký tự ‘@’. Trong

trường hợp này, khung nhìn cần gởi các sự kiện thả “giả” cho Control và Alt

155

nhằm để ký tự ‘@’ thông dịch đúng (ctrl-alt-q có thể có nghĩa gì đó hoàn

toàn khác đối với server).

• Không có chuẩn chung cho “tab lùi” trong Hệ thống X Windows. Trên một

số hệ thống shift-tab cho keysym “ISO_Left_Tab”, trên số khác nó cho ra

keysym “BackTab” dùng riêng và trên số còn lại nó cho “Tab” và các ứng

dụng lấy từ tình trạng phím shift để biết nó là tab lùi hay tab tiến. Trong nghi

thức RFB cách tiếp cận sau được ưa chuộng hơn. Khung có thể phát sinh

một Tab kèm shift nhấn hơn là một ISO_Left_Tab. Tuy thế, để tương thích

với một số khung nhìn có sẵn, server cần nhận ra ISO_Left_Tab như là một

Tab kèm shift nhấn.

4.1.6.3.6 Sự kiện trỏ

cho biết con trỏ có di chuyển hoặc nút trỏ được nhấn hoặc thả. Con trỏ đang ở vị

trí (x-position, y-position), và trạng thái của các nút 1 đến 8 tính theo thứ tự từ bit 0 đến

7 của button-mask, giá trị bit 0 là thả, giá trị bit 1 là nhấn

Trên một mouse chuẩn, các nút 1, 2 và 3 tương ứng cho các nút trái, giữa và

phải trên mouse. Trên mouse có wheel (bộ phận scroll), mỗi bước quay wheel lên

tương ứng với việc nhấn và thả nút 4, và mỗi bước quay wheel xuống tương úng với

việc nhấn và thả nút 5.

Số byte

Type [Giá trị] Mô tả

dạng thông điệp

U8 5

1

button-mask

U8

1

x-position

U16

2

y-position

U16

2

4.1.6.3.7 ClientCutText

156

Client có dạng văn bản mới ISO 8859-1 (Latin-1) trong vùng cắt văn bản của

nó. Hết mỗi dòng biểu thị bởi ký tự đơn linefeed / newline (sang dòng mới, giá trị 10),

không cần giá trị carriage-return (trở về đầu dòng, giá trị 13). Hiện tại chưa có cách

chuyển đổi văn bản ngoài bộ ký tự Latin-1.

Số byte

Type [Giá trị] Mô tả

1

U8 6

dạng thông điệp

3

độn

4

U32

độ dài chuỗi

Độ dài chuỗi

mảng U8

văn bản

4.1.6.4 Các thông điệp từ server đến client

4.1.6.4.1 FramebufferUpdate

Một cập nhật vùng đệm khung gồm một tuần tự các chữ nhật dữ liệu điểm ảnh

client phải vẽ lên vùng đệm khung của nó. Thông điệp được gởi hồi đáp cho một

FramebufferUpdateRequest từ client. Chú ý rằng có một quá trình bất tận việc gởi và

nhận các FramebufferUpdateRequest và FramebufferUpdate.

Số byte

Type [Giá trị] Mô tả

U8 0

dạng thông điệp

1

độn

1

U16

số các chữ nhật

2

157

đi kèm theo là số các chữ nhật dữ liệu điểm ảnh. Mỗi hình chữ nhật bao gồm:

Số byte

Type [Giá trị] Mô tả

2

U16

x-position

2

U16

y-position

2

U16

width

2

U16

height

4

U32

dạng mã hóa

0

mã hóa thô (raw)

1

mã hóa CopyRect

2

mã hóa RRE

4

mã hóa CoRRE

5

mã hóa Hexile

16

mã hóa ZRLE

0xffffff11

mã hóa giả Cursor

0xffffff21

mã hóa giả DesktopSize

Các mã hóa khác

6, 7, 8

zlib, tight, zlibhex

0xffffff00

đến

0xffffff10

0xffffff12

đến

các tùy chọn của tight

0xffffff20

0xffffff22

đến

0xffffffff

158

tiếp theo là các dữ liệu điểm ảnh trong dạng mã hóa đã xác định. Xem

phần 4.3.6.5 cho định dạng dữ liệu cho mỗi mã hóa và xem phần 4.3.6.6 cho định

nghĩa của mã hóa giả.

4.1.6.4.2 SetColourMapEntries

Khi định dạng điểm ảnh dùng “bản đồ ảnh”, thông điệp này báo cho client biết

những giá trị điểm ảnh xác định trước cần ánh xạ vào các cường độ RGB.

Số byte

Type [Giá trị] Mô tả

1

U8 1

dạng thông điệp

1

độn

2

U16

màu đầu tiên

2

U16

số lượng màu

tiếp theo là lặp đi lặp lại số lượng màu các dữ liệu như sau

Số byte

Type [Giá trị] Mô tả

đỏ

U16

2

xanh lá

U16

2

xanh dương

U16

2

4.1.6.4.3 Bell

Bật loa chuông nếu client có.

Số byte

Type [Giá trị] Mô tả

1

U8 2

dạng thông điệp

4.1.6.4.4 ServerCutText

Client có dạng văn bản mới ISO 8859-1 (Latin-1) trong vùng cắt văn bản của

nó. Hết mỗi dòng biểu thị bởi ký tự đơn linefeed / newline (sang dòng mới, giá trị 10),

159

không cần giá trị carriage-return (trở về đầu dòng, giá trị 13). Hiện tại chưa có cách

chuyển đổi văn bản ngoài bộ ký tự Latin-1.

Số byte

Type [Giá trị] Mô tả

1

U8 6

dạng thông điệp

3

độn

4

U32

độ dài chuỗi

Độ dài chuỗi

mảng U8

văn bản

4.1.6.5 Các mã hóa

4.1.6.5.1 Mã hóa thô

Mã hóa đơn giản nhất là dữ liệu điểm ảnh thô. Trong trường hợp này, dữ liệu

chứa width x height các giá trị điểm ảnh (với width và height là chiều dài và chiều rộng

của hình chữ nhật). Các giá trị chỉ đơn giản biểu thị các điểm ảnh theo thứ tự đường

quét từ trái sang phải. Mọi client RFB đều phải bắt buộc hiểu dữ liệu điểm ảnh dưới

dạng mã hóa thô, và các server chỉ gởi dạng mã hóa thô nếu client không chỉ rõ dạng

mã hóa.

Số byte

Type [Giá

Mô tả

trị]

width x height x bytesPerPixel mảng PIXEL

các điểm ảnh

4.1.6.5.2 Mã hóa CopyRect

Mã hóa CopyRect (sao chép hình chữ nhật) là dạng mã hóa rất đơn giản và hiệu

quả được dùng khi client đã có sẵn dữ liệu điểm ảnh như thế trong vùng đệm khung

của nó. Mã hóa trên đường truyền chỉ đơn giản gồm 2 tọa độ X, Y. Hai tọa độ này cho

biết vị trí trong vùng đệm khung mà client sẽ sao chép hình chữ nhật dữ liệu điểm ảnh

vào. Điều này được ứng dụng trong nhiều tình huống, hiển nhiên nhất là việc người

160

dùng dời một cửa sổ trên màn hình, và khi nội dung của cửa sổ bị cuộn. Một ứng dụng

ít thấy hơn là tích gợp việc việc vẽ văn bản hay lặp lại các mẫu. Một server thông minh

sẽ có thể gởi tường minh một mẫu chỉ một lần, và biết vị trí trước đó của mẫu trong

vùng đệm khung, gởi từ từ các xuất hiện của mẫu sử dụng mã hóa CopyRect.

Số byte

Type [Giá

Mô tả

trị]

2

U16

src-x-position

2

U16

src-y-position

4.1.6.5.3 Mã hóa RRE

RRE viết tắt của rise- and-run-length encoding (mã hóa chiều dài tăng trưởng

và chạy) và như tên ngầm định của nó, mã hóa cần một mã hóa chiều dài chạy (thay

đổi) tương tự hai chiều. Các hình chữ nhật mã hóa RRE đến client trong dạng mà có

thể dựng hình ngay lập tức và hiệu quả bởi các engine đồ họa đơn giản nhất. RRE

không thích hợp với các máy desktop phức tạp, nhưng có thể hữu dụng trong một số

trường hợp.

Ý tưởng căn bản đằng sau RRE là phân vùng một hình chữ nhật dữ liệu điểm

ảnh thành các vùng hình chữ nhật con (các hình chữ nhật phụ), mỗi cái trong chúng

chứa các điểm ảnh của một giá trị đơn và hợp của những cái tạo thành vùng hình chữ

nhật ban đầu. Việc phân vùng gần như tối ưu của một hình chữ nhật cho trước thành

các hình chữ nhật con thì khá dễ tính.

Mã hóa bao gồm một giá trị điểm ảnh nền, Vb (đặc trưng cho hầu hết giá trị

điểm ảnh trong hình chữ nhật) và một biến đếm N, kèm theo một danh sách N các hình

chữ nhật, mỗi cái chứa một tuple với v ((cid:0) Vb ) là giá trị điểm ảnh, (x, y)

là vị trí tọa độ của hình chữ nhật con tương ứng với góc trên trái của hình chữ nhật, và

(w, h) là chiều rộng và dai của hình chữ nhật con. Client có thể dựng hình chữ nhật ban

161

đầu bằng cách vẽ một hình chữ nhật tô bằng gía trị điểm ảnh nền và sau đó vẽ hình chữ

nhật tô dựa theo các hình chữ nhật con.

Trên đường truyền, dữ liệu được bắt đầu với tiêu đề:

Số byte

Type [Giá

Mô tả

trị]

4

U16

số lượng hình chữ nhật con

PIXEL

số byte mỗi điểm ảnh

giá trị điểm ảnh nền

Đi kèm là số lượng hình chữ nhật con các instance (hiển thị) của cấu trúc:

Số byte

Type [Giá trị] Mô tả

PIXEL

số byte mỗi điểm ảnh

giá trị điểm ảnh hình chữ nhật

2

U16

con

2

U16

x-position

2

U16

y-position

2

U16

width

height

4.1.6.5.4 Mã hóa CoRRE

Chú thích: mã hóa CoRRE đã bị bỏ - Hextile là mã hóa tốt hơn dùng cùng ý

tưởng.

CoRRE (Compact RRE) là một biến thể của RRE, với việc chúng ta sẽ bảo đảm

hình chữ nhật lớn nhất được gởi không quá 255x255 điểm ảnh. Một server muốn

gởi một điểm ảnh lớn hơn thế chỉ đơn giản là cắt nhỏ ra và gởi các hình chữ nhật

RFB nhỏ hơn. Trong mỗi hình chữ nhật nhỏ hơn đó, một byte đơn sẽ biểu thị các

chiều của hình chữ nhật con. Với một desktop đặc trưng, điều này cho nén tốt hơn

cho RRE. Thực tế, việc nén tốt nhất đạt được khi chúng ta giới hạn hơn nữa kích

162

thước hình chữ nhật – cài đặt hiện tại đang dùng tối đa 48x48. Điều này có được là

bởi vì các hình chữ nhật không được mã hóa tốt (tiêu biểu là những cái chứa dữ liệu

hình ảnh) được gởi dạng thô, trong khi những cái khác mã hóa tốt gởi theo CoRRE.

Kícht thước tối đa hình chữ nhật càng nhỏ, việc mã hóa càng tốt (ít hình chữ nhật

thô hơn). Với RRE, cả hình chữ nhật gốc một là gởi theo RRE, hai là gởi theo thô.

Tuy nhiên, vì có một số lượng nhất định hao phí gánh chịu từ mỗi hình chữ nhật

RFB, làm cho kích thước tối đa hình chữ nhật quá nhỏ (và từ đó làm tăng số lượng

hình chữ nhật RFB), dẫn đến việc nén kém hiệu quả hơn.

Dữ liệu bắt đầu bằng tiêu đề:

Số byte

Type [Giá

Mô tả

trị]

4

U16

số lượng hình chữ nhật con

PIXEL

số byte mỗi điểm ảnh

giá trị điểm ảnh nền

Đi kèm là số lượng hình chữ nhật con các instance (hiển thị) của cấu trúc:

Số byte

Type [Giá trị] Mô tả

PIXEL

giá trị điểm ảnh hình chữ nhật

số byte mỗi điểm ảnh

2

U16

con

2

U16

x-position

2

U16

y-position

2

U16

width

height

4.1.6.5.5 Mã hóa Hextile

Hextile là một biến đổi của ý tưởng CoRRE. Các hình chữ nhật được cắt ra các

tile (lát) 16x16, cho phép các chiều hình chữ nhật xác định bằng mỗi 4 bit, tổng cộng

16 bit. Không giống CoRRE, các lát không phải là các hình chữ nhật RFB cơ bản nhất.

163

Khi cắt một hình chữ nhật gốc thành các lát, điều này thực hiện theo tính tóan trước.

Điều này có nghĩa là vị trí và kích thước của mỗi lát không cần phải xác định tường

minh – nội dung mã hóa của các lát chỉ đơn giản theo một lát khác trong thứ tự tính

toán trước. Sắp xếp thứ tự các lát chúng ta dùng thì phải bắt đầu từ góc trái trên đi theo

từ trái qua phải, từ trên xuống dưới. Nếu độ rộng của hình chữ nhật không chính xác là

bội số của 16 thì độ rộng của lát cuối trên mỗi dòng sẽ nhỏ lại tương ứng.Tương tự nếu

độ dài của hình chữ nhật không chính xác là bội số của 16 thì độ dài của mỗi lát trên

dòng cuối sẽ nhỏ lại tương ứng.

Mỗi lát mã hóa hoặc thô hoặc là biến thể RRE. Mỗi lát có một giá trị điểm ảnh

nền, như đề cập ở trên. Tuy nhiên, giá trị nền không cần xác định tường minh cho một

lát cho trước nếu nó giống với nền của lát trước đó. Nếu mọi hình chữ nhật con của

một lát có cùng giá trị điểm ảnh, giá trị này có thể xác định đúng một lần thành giá trị

điểm ảnh mặt tiền cho cả lát. Cũng như nền, giá trị điểm ảnh mặt tiền có thể để trống,

ngụ ý nó đã có trong lát trước rồi.

Do vậy, dữ liệu mỗi lát mã hóa theo thứ tự. Mỗi lát bắt đầu bằng byte dạng

subencoding (mã hóa phụ), mang ý nghĩa mặt nạ áp cho số bit:

Số byte

Type [Giá trị] Mô tả

1

U8

subencoding-mask

1

Thô (raw)

2

BackgroundSpecified

4

ForegroundSpecified

6

AnySubrects

16

SubrectsColoured

Nếu bit Raw được đặt lên thì các bit còn lại không liên quan; width x height giá

trị điểm ảnh tiếp theo (với widht và height là độ rộng và dai của lát). Nếu không các bit

còn lại trong mặt nạ phải như sau:

164

BackgroundSpecified – nếu đặt, một giá trị điểm ảnh theo sau sẽ xác định màu nền

cho lát này:

Số byte

Type [Giá trị] Mô tả

PIXEL

số byte mỗi điểm ảnh

giá trị điểm ảnh nền

Lát đầu tiên trong một hình chữ nhật phải có bt đặt lên. Nếu bit này không đặt

thì nền sẽ giống với lát cuối.

ForegroundSpecified – nếu đặt, giá trị điểm ảnh theo sau sẽ xác định giá trị màu mặt

tiền được dùng cho mọi hình chữ nhật con của lát này:

Số byte

Type [Giá trị] Mô tả

PIXEL

số byte mỗi điểm ảnh

giá trị điểm ảnh mặt tiền

Nếu bit này được thì bit SubrectsColoured phải là 0.

AnySubrects – nếu đặt, một byte đơn theo sau cho biết số lượng các hình chữ nhật con:

Type [Giá trị] Mô tả

Số byte

U8

1

số lượng hình chữ nhật

Nếu không đặt, không có hình chữ nhật con (i.e. cả lát chỉ là một màu nền trơ).

SubrectsColoured – nếu đặt thì mỗi hình chữ nhật con sẽ đi kèm giá trị điểm ảnh cho

biết màu của hình chữ nhật con, vậy một hình chữ nhật con gồm:

Số byte

Type [Giá trị] Mô tả

PIXEL

giá trị điểm ảnh hình chữ nhật

số byte mỗi điểm ảnh

U8

1

con

U8

1

x-and-y-position

165

width-and-height

Nếu không đặt, mọi hình chữ nhật con có cùng màu, màu mặt tiền; nếu bit

ForegroundSpecified không được đặt thì mặt tiền sẽ giống với lát cuối. Một hình chữ

nhật con là:

Số byte

Type [Giá trị] Mô tả

U8

1

x-and-y-position

U8

1

width-and-height

Vị trí và kích thước của mỗi hình chữ nhật con xác định trong hai byte,

x-and-y-position và width-and-height. Bốn bit quan trọng nhất của x-and-y-position

xác định vị trí X, bốn bít còn lại xác định vị trí Y. Bốn bit quan trọng nhất của width-

and-height xác định độ rộng trừ đi một, bốn bít còn lại xác định độ dài trừ đi một.

4.1.6.5.6 Mã hóa ZRLE

ZRLE viết tắt cho Zlib Run-Length Enconding, là kết hợp của khả năng nén

theo zlib, cắt lát, phân bảng màu và mã hóa chiều dài chạy. Trên đường truyền, hình

chữ nhật bắt đầu với một trường rộng 4 byte, và theo sau là những byte dữ liệu nén

theo zlib. Một đối tượng “theo dòng” zlib đơn được dùng cho một kết nối RFB cho

trước, để các hình chữ nhật ZRLE phải được mã hóa và giải mã nghiêm ngặc theo thứ

tự.

Số byte

Type [Giá trị] Mô tả

4

U32

chiều dài

mảng U8

zlibData (dữ liệu zlib)

chiều dài

166

zlibData khi được bung nén hiển thị bằng các lát 64x64 điểm ảnh theo thứ tự

trái qua phải, trên xuống dưới, tương tự như hextile. Nếu độ rộng của hình chữ nhật

không chính xác là bội số của 64 thì độ rộng của lát cuối trên mỗi dòng sẽ nhỏ lại

tương ứng.Tương tự nếu độ dài của hình chữ nhật không chính xác là bội số của 64 thì

độ dài của mỗi lát trên dòng cuối sẽ nhỏ lại tương ứng.

ZRLE sử dụng kiểu dữ liệu mới CPIXEL (compressed pixel – điểm ảnh nén).

Kiểu này cũng giống như PIXEL cho định dạng điểm ảnh đã xác định trước, ngoại trừ

cờ

true-colour là khác 0, số bit mỗi điểm ảnh là 32, độ sâu là 24 hay thấp hơn và mọi bit

tạo cường độ đỏ, xanh lá, xanh dương gắn vừa vào 3 byte thứ yếu nhất hoặc 3 byte

quan trọng nhất Trong trường hợp này, một CPIXEL chỉ dài độ 3 byte, và chứa 3 byte

thứ yếu nhất hay 3 byte quan trọng nhất, tùy bên nào phù hợp hơn. bytePerCPixel là số

byte trong CPIXEL.

Mỗi lát bắt đầu bằng một byte dạng subendcoding. Bit cao nhất của byte này đặt

lên nếu lát được mã hóa chiều dài chạy, nếu không sẽ xóa. Bảy bit dưới cho biết kích

thước của bảng màu dùng – 0 có nghĩa là không có bảng màu, một có nghĩa là lát có

một màu đơn, 2 đến 127 cho biết bảng màu có kích thước như thế. Các giá trị có thể có

của subencoding là:

0 – dữ liệu điểm ảnh thô. width x height giá trị điểm ảnh tiếp theo (với width và height

là độ rộng và độ dài của lát):

Số byte

Type [Giá

Mô tả

trị]

width

x

height

x

mảng CPIXEL

các điểm ảnh

bytesPerCPixel

167

1 – một lát cứng là một lát chỉ có một màu đơn:

Số byte

Type [Giá

Mô tả

trị]

CPIXEL

bytesPerCPixel

pixelValue – giá trị điểm

ảnh

2 to 16 – các dạng bảng màu đóng gói. Theo sau bảng màu, bao gồm các paletteSize

(= subencoding) giá trị điểm ảnh. Sau các điểm ảnh đóng gói, mỗi điểm ảnh được biểu

diễn bằng một trường bit cho biết chỉ mục cho bảng màu (0 có nghĩa là mục đầu tiên

bảng màu ). Cho paletteSize bằng 2, trường 1 bit được dùng, cho paletteSize bằng 3

hay 4, trường 2 bit được dùng, và cho paletteSize từ 5 đến 16, trường 4 bit được dùng.

Các trường bit đóng gói trong các byte, các bit quan trọng nhất biểu diễn các điểm ảnh

cực trái (i.e. big endian). Cho các lát không rộng bằng bội số 8, 4 hay 2 điểm ảnh, các

bit độn sẽ dùng để canh lề mỗi dòng cho chính xác số lượng byte.

Số byte

Type [Giá

Mô tả

trị]

paletteSize x bytesPerCPixel

mảng CPIXEL

bảng màu

mảng U8

m

các điểm ảnh đóng gói

17 đến 127 – không dùng (không có tiến triển trên bảng màu RLE).

128 – RLE trơ, bao gồm số lượng các đường chạy, lặp lại cho đến khi lát gởi hết.

Đường chạy có thể bắt đầu từ cuối một dòng sang bắt đầu dòng kế tiếp. Mỗi đường

chạy được biểu diễn bởi một giá trị điểm ảnh đơn theo sau là chiều dài của đường chạy.

Chiều dài biểu diễn một hoặc nhiều byte. Chiều dài được tính nhiều hơn một so với

tổng các byte cho biết độ dài. Bất kỳ giá trị byte khác 255 đều được xem là byte cuối.

168

Ví dụ, chiều dài 1 biểu diễn [0], 255 là [254], 256 là [255, 0], 257 là [255, 1], 510 là

[255, 254] , 511 là [255, 255, 0] ...

Số byte

Type [Giá

Mô tả

trị]

U8

paletteIndex + 128

1

mảng U8 255

floor((runLength – 1)/255)

U8

(runLength – 1)%255

1

4.1.6.6 Mã hóa giả

4.1.6.6.1 Mã hóa giả Cursor

Một client yêu cầu mã hóa giả Cursor phải khai báo nó có thể vẽ con trỏ mouse

cục bộ được. Điều này có thể làm tăng một cách đáng kể việc trình diễn trên các đường

truyền tốc độ thấp. Server thiết lập hình dạng con trỏ bằng cách gởi một hình chữ nhật

giả với mã hóa giả Cursor là một phần của việc cập nhật. Các tọa độ x-position và y-

position của hình chữ nhật giả cho biết hotspot (đầu trỏ) của con trỏ, và width và height

cho biết độ rộng và dài của con trỏ tính bằng điểm ảnh. Dữ liệu gồm width x height

giá trị điểm ảnh đi kèm là một mặt nạ bit. Mặt nạ bit gồm các dòng quét từ trái sang

phải, từ đỉnh xuống dưới, mỗi dòng quét được độn thêm vào một số các byte tính bằng

floor((width+ 7)/8). Trong mỗi byte, bit quan trọng nhất biểu diễn điểm ảnh cực trái,

với một bit đó mang ý nghĩa điểm ảnh tương ứng trong con trỏ có hiệu lực.

Số byte

Type [Giá

Mô tả

trị]

width x height x bytesPerPixel mảng PIXEL

các điểm ảnh của con trỏ

169

mảng U8

floor((width + 7)/8) * height

mặt nạ bit

4.1.6.6.2 Mã hóa giả DesktopSize

Một client yêu cầu mã hóa giả Cursor phải khai báo nó có thể sao chép với sự

thay đổi trong độ rộng và/ hay độ dài vùng đệm khung. Server thay đổi kích thước

desktop bằng cách gởi một hình chữ nhật giả với mã hóa giả DesktopSize như là hình

chữ nhật cuối cùng của quá trình cập nhật. Các tọa độ x-position và y-position bỏ qua,

và width và height cho biết độ rộng và độ dài của vùng đệm khung mới. Không có dữ

liệu kèm theo với hình chữ nhật giả.

4.2 H323

4.2.1 Chuẩn H323 là gì ?

H.323 là chuẩn của International Telecommunications Union(ITU), cung cấp

những đặc điểm kỹ thuật cho máy tính, thiết bị, và dịch vụ cho việc giao tiếp đa truyền

thông qua mạng mà không cần phải quan tâm đến chất lượng dịch vụ. Các máy tính và

thiết bị có sử dụng H.323 có thể đem đến âm thanh, hình ảnh hay dữ liệu theo thời gian

thực. Chuẩn này dựa trên Internet Engineering Task Force (IETF), Real Time Protocol

(RTP) và Real Time Control Protocol (RTCP), cộng với một số protocol được thêm

vào cho việc thực hiện cuộc gọi, trao đổi dữ liệu và giao tiếp âm thanh, hình ảnh theo

thời gian thực.

Người dùng có thể kết nối với người khác thông qua internet và sử dụng

những loại sản phẩm khác nhau có hỗ trợ H.323. H.323 định nghĩa cách mà thông tin

được định dạng và đóng gói trước khi truyền qua mạng. Mã hóa âm thanh và hình ảnh,

và giải mã đầu vào/ đầu ra từ nguồn âm thanh, hình ảnh cho việc giao tiếp giữa các

điểm. Một codec( bao gồm mã hóa và giải mã) sẽ chuyển đổi tín hiệu âm thanh và hình

ảnh giữa hình thức tương tự và số.

170

H.323 cũng xác định dịch vụ T.120 cho việc trao đổi dữ liệu và hội nghị trong

một phiên của H.323. Quan trọng nhất, T.120 này hỗ trợ việc xử lý dữ liệu chung với

âm thanh và hình ảnh của H.323 hay riêng lẻ.

Microsoft và trên 120 công ty hàng đầu khác đã tuyên bố dự định của họ trong

việc hỗ trợ và áp dụng H.323 trong sản phẩm và dịch vụ của họ. Với sự hỗ trợ rộng lớn

này, H.323 sẽ là một chuẩn cho hội nghị âm thanh, hình ảnh qua Internet.

4.2.2 Những lợi ích của H.323

4.2.2.1

Chuẩn mã hóa

H.323 thiết lập chuẩn cho việc nén và giải nén dòng dữ liệu âm thanh và hình

ảnh, bảo đảm những thiết bị từ những hãng khác nhau có một vài lãnh vực hỗ trợ

chung.

4.2.2.2

Khả năng liên kết hoạt động:

Người dùng muốn dùng hội nghị sẽ không lo lắng giữa các điểm nhận. Ngoài

việc đảm bảo rằng các điểm nhận sẽ giải mã được thông tin, H.323 thiết lập phương

thức cho người dùng ở nơi nhận có thể giao tiếp đúng với người gởi. Chuẩn này cũng

thiết lập cách thiết lập cuộc gọi và những nghi thức điều khiển.

4.2.2.3

Độc lập với mạng:

H.323 được thiết kế để chạy bên trên kiến trúc mạng thông thường. Khi kỹ

thuật mạng phát triển, và khi kỹ thuật quản lý băng thông được củng cố, những giải

pháp dựa trên H.323 sẽ có nhiều tiện ích từ những khả năng được củng cố này.

171

4.2.2.4

Độc lập với nền và ứng dụng:

H.323 không gắn chặt với phần cứng hay ứng dụng nào. Những nền tảng

tương thích H.323 sẽ được dùng trong nhiều kích cỡ và hình dáng, bao gồm máy tính

cá nhân có hỗ trợ video, nền tảng chuyên dụng, thiết bị di động dựa trên IP v.v…

4.2.2.5 Hỗ trợ đa điểm :

Mặc dù H.323 có thể hổ trợ hội nghị với ba hay nhiều điểm mà không đòi hỏi

một thiết bị điều khiển đa điểm. Khả năng này được bao gồm trong các thành phần của

H.323

4.2.2.6 Quản lý băng thông:

Luồng âm thanh và hình ảnh thì tốn băng thông

và có thể làm cản trở sự

hoạt động của mạng. H.323 giải quyết vấn đề này bằng cách cung cấp cách quản lý

băng thông. Nhà quản lý mạng có thể hạn chế số kết nối H.323 đồng thời trong mạng

của họ hay lượng băng thông có giá trị trong ứng dụng dùng H.323. Những điều này

đảm bảo rằng vấn đề về lưu lượng sẽ bị xóa bỏ.

4.2.2.7 Hỗ trợ một nhiều:

Trong hội nghị đa điểm , H.323 hỗ trợ việc truyền dữ liệu một nhiều. Gởi một

nhiều sẽ gởi gói tin 9ến một số đích mà không cần hồi đáp. Truyền theo một nhiều sử

dụng băng thông một cách hiệu quả hơn vì tất cả thiết bọ trên mạng đều đọc trong cùng

một nhóm cùng đọc được từ một luồng dữ liệu

4.2.2.8

Tính linh họat:

Hội nghị sử dụng H.323 có thể sử dụng nhiều điểm cuối với những khả năng

khác nhau. Ví dụ, thiết bị đầu cuối với khả năng chỉ có âm thanh có thể tham gia vào

hội nghị với thiết bị có khả năng âm thanh hay dữ liệu. Hơn nữa thiết bị đa truyền

thông H.323 có thể chia sẻ phần dữ liệu của một hội nghị có hình ảnh với thiết bị chỉ

172

có dữ liệu dựa trên T.120 trong khi chia sẻ tiếng nói, hình ảnh và dữ liệu với các thiết

bị H.323 khác.

4.2.2.9 Hội nghị thông qua mạng

Nhiều người dùng muốn thiết lập hội nghị từ mạng LAN đến mạng ở xa. Ví

dụ, H.323 thiết lập phương tiện để liên kết hệ thống máy vi tính dựa trên mạng LAN

với hê thống dựa trên ISDN. H.323 sử dụng kỹ thuật mã hóa thông dụng từ chuẩn của

hội nghị có hình ảnh để làm giảm độ trễ và cung cấp sự thể hiện tối ưu.

4.2.3 Những chuẩn nào áp dụng đến H.323

4.2.3.1

Tín hiệu gọi và điều khiển:

H.323: hệ thông giao tiếp đa phương tiện dựa trân gói

H.225: chuẩn điều khiển cuộc gọi

H.235: bảo mật

H.245: chuẩn điều khiển phương tiện truyền

Q.931: cung cấp tín hiệu số

H.450.1: chuẩn cho sự hỗ trợ các dịch vụ thêm vào H.323

4.2.3.2 Mã hóa và giải mã âm thanh:

G.711 : Mã hóa và giải mã âm thanh PCM 56/64 kpbs

G.722 : Mã hóa và giải mã âm thanh cho 7Khz ở 48/56/64kbps

G.723.1 : Mã hóa và giải mã tiếng nói cho 5.3 và 6.3 kbps

G.728 : Mã hóa và giải mã tiếng nói cho 16 kbps

G.729 : Mã hóa và giải mã tiếng nói cho 8/16 kbps

4.2.3.3 Mã hóa và giải mã hình ảnh:

H.261: Mã hóa và giải mã hình ảnh >=64kbps

173

H.263: Mã hóa và giải mã hình ảnh <64kbps

4.2.3.4

Những chuẩn có liên quan: H.320 , H.324, T120

4.2.4 Kiến trúc H.323

H.323 định nghĩa bốn thành phần chính yếu cho hệ thống giao tiếp trên mạng:

Terminals, Gateways, Gatekeepers, and Multipoint Control Units

4.2.4.1

Terminals:

Terminals là thiết bị cuối bên người dùng cung cấp sự giao tiếp hai chiều và

theo thời gian thực. Tất cả các terminals phải hỗ trợ giao tiếp âm thanh, hình ảnh và dữ

liệu là tùy chọn.

Tất cả các H.323 terminals hỗ trợ H.245, sử dụng hỗ trợ thương lượng kênh

truyền và khả năng. Ba thành phần khác đòi hỏi phải có là: Q.931 cho báo hiệu và thiết

lập cuộc gọi, RAS (Registration/Admission/Status) để giao tiếp với GatewayKeeper và

RTP/RTPC cho việc quản lý thứ tự các gói tin âm thanh và hình ảnh.

Các thành phần tùy chọn trong H.323 terminals là codec hình ảnh, T.120,

MCU.

4.2.4.2 Gateways:

Là thành phần tùy chọn trong hội nghị dùng H.323. Gateway cung cấp nhiều

dịch vụ. Ví dụ: chức năng chuyển đổi giữa các định dạng truyền dữ liệu (H.225 và

H.242)và các thủ tục giao tiếp (H.245 và H.242). Hơn nữa, Gateway cung có thể

chuyển đổi giữa việc mã hóa âm thanh và hình ảnh và thực hiện các cuộc gọi và kết

thúc cả trên mạng LAN và mạng theo cơ chế chuyển mạch

Nói chung, mục đích của Gateway là phản ánh đặc điểm của thiết bị đầu cuối

LAN và thiết bị đầu cuối SCN và ngược lại. Ứng dụng chính của gateway là :

Thiết lập đường kết nối với thiết bị đầu cuối tín hiệu tương tự PSTN

174

Thiết lập đường kết nối với thiết bị đầu cuối hỗ trợ H.320 từ xa thông qua

mạng chuyển mạch dựa trên ISDN.

Thiết lập đường kết nối với thiết bị đầu cuối hỗ trợ H.324 từ xa thông qua

mạng PSTN.

Gateway không đòi hỏi nếu kết nối với mạng khác không có vì điểm cuối phải

giao tiếp trực tiếp với điểm cuối khác trên cùng mạng LAN. Terminals giao tiếp với

Gateway thông qua chuẩn H.245 và Q.931.

Hình 4-2 Gateway Proticol Stack

4.2.4.3 Gatekeeper:

GateKeeper là thành phần quan trọng nhất trong mạng có sử dụng H.323. Nó

hoạt động như là trung tâm của mọi cuộc gọi trong vùng của nó và cung cấp các dịch

vụ điều khiển cuộc gọi để đăng ký đến điểm cuối. Trong nhiều trường hợp khác nhau

thì thì gatekeeper hoạt động như là một switch ảo.

GateKeeper thực hiện hai chức năng điều khiển cuộc gọi quan trọng. Thứ nhất

là chuyển địa chỉ từ định danh mạng LAN cho thiết bị và gateway sang địa chỉ IP hay

IPX. Thứ hai là quản lý băng thông

175

Tập hợp tất cả Terminals, Gateways, MultiPoint Control Unit quản lý bởi một

GateKeeper duy nhất thì được xem như là một vùng H.323

Một đặc điểm tùy chọn nhưng có giá trị là khả năng tìm đường cho cuộc gọi

H.323. Bằng cách dẫn đường một cuộc gọi thông qua GateKeeper, cuộc gọi có thể

được điều khiển một cách hiệu quả hơn. Những người cung cấp dịch vụ cần khả năng

này để tính tiền cho cuộc gọi thông qua mạng của họ. Dịch vụ này cũng có thể hướng

cuộc gọi đến một điểm cuối khác nếu điểm cuối được gọi không có giá trị. Hơn nữa,

một khả năng của GateKeeper về việc dẫn đường cho cuộc gọi có thể giúp cho việc

quyết định cân băng giữa nhiều gateway.

Trong khi, Gatekeeper về mặt luận lý thì độc lập với điểm cuối H.323, tuy

nhiên nhiều nhà sản xuất tích hợp chức năng Gatekeeper vào trong việc thực thi vật lý

của Gateways và MCU.

Một Gatekeeper không đòi hỏi trong hệ thống H.323. Tuy nhiên nếu có

Gatekeeper, terminal có thể sử dụng các dịch vụ cung cấp bởi Gatekeeper. RAS định

nghĩa gồm chuyển đổi địa chỉ, điều khiển về quyền, điều khiển băng thông, và quản lý

vùng.

Gatekeeper cũng có vai trò trong việc kết nối đa điểm. Để hỗ trợ cho hội nghị

đa điểm, người dùng phải sử dụng một Gatekeeper để nhận kênh điều khiển H.245 từ

hai terminals trong hội nghị điểm nối điểm. Khi dạng hội nghị này chuyển sang đa

điểm, Gatekeeper có thể chuyển hướng kênh điều khiển H.245 sang MC(multiple

Controller). Gatekeeper không xử lý tính hiệu mà chuyển tín hiểu giữa các terminal

hay giữa terminal và MC.

Chức năng bắt buộc của một Gatekeeper

1.Chuyển địa chỉ: Những cuộc gọi bên trong mạng H.323 có thể dùng định

danh để đánh địa chỉ cho các thiết bị đầu cuối. Những cuộc gọi có nguồn gốc bên ngòai

mạng H.323 và nhận bởi gateway có thể sử dụng một số điện thọai E.164 (ví dụ 310-

442-9222) để đánh địa chỉ cho thiết bị đầu cuối. Gatekeeper chuyển số điện thọai

176

E.164 này hay định danh sang địa chỉ mạng. Việc chuyển này sử dụng một bảng được

Update bởi Registration message.

2. Điều khiền quyền: Gatekeeper có thể điều khiển quyền của điểm cuối khi

truy cập vào mang H.323. Nó sử dụng RAS message, ARQ( Admission Request), ACF

(confirm), và Reject(ARJ). Nếu điều khiển quyền không có gì thì mọi yêu cầu đều cho

phép.

3. Điều khiển băng thông:

Hỗ trợ cho yêu cầu băng thông, xác định và từ chối thông điệp. Điều này có

thể dựa vào việc quản lý băng thông. Nếu điều khiển băng thông không có gì thì mọi

yêu cầu đều cho phép.

4.Quản lý vùng: Gatekeeper cung cấp những chức năng trên cho terminal,

MCU, Gateway…đã được đăng ký trong vùng của nó điều khiển

Những chức năng bổ sung Gatekeeper bao gồm:

1. Tín hiệu điều khiển cuộc gọi: Trong hội nghị điểm nối điểm, Gatekeeper có

thể xử lý tín hiệu điều khiển cuộc gọi Q.931. Như một sự lựa chọn, Gatekeeper có thể

gởi tín hiệu Q.931 ở những điểm cuối đến trực tiếp với nhau.

2. Quyền cuộc gọi: Gatekeeper có thể từ chối cuộc gọi từ terminal dựa trên

đặc điểm kỹ thuật của Q.931. Lý do từ chối có thể bao gồm hạn chế truy cập đến hay đi

từ các terminal hay gateway đặc biệt, hạn chế truy cập trong một khoảng thời gian.

Tiêu chuẩn để xác định quyền thành công hay thất bại là ngoài phạm vi của H.323.

3. Quản lý băng thông: Gatekeeper có thể từ chối tất cả các cuộc gọi từ một

terminal nếu nó thấy rằng băng thông tối thiểu không có. Chức năng này cũng hoạt

động trong lúc đang gọi nếu terminal đòi hỏi thêm băng thông. Tiêu chuẩn cho việc

quyết định băng thông có đủ hay không nằm ngoài phạm vi của H.323

4. Quản lý cuộc gọi: Gatekeeper có thể duy trì danh sách các cuộc gọi H.323

đang diễn ra để chỉ ra ràng terminal bận hay cung cấp thông tin cho chức năng quản lý

băng thông.

177

Hình 4-3 Các thành phần của gatekeeper

4.2.4.4 Multipoint Control Unit (MCU)

Multipoint Control Unit (MCU) hỗ trợ hội nghị giữa ba hay nhiều điểm cuối.

Dưới H.323, MCU bao gồm một Multipoint Controller(MC), bắt buộc, và có hay

không Multipoint Processor(MP). MC nắm giữ những cuộc thương lượng H.245 giữa

tất cả các terminals, để xác định khả năng thông dụng nhất cho việc xử lý âm thanh và

hình ảnh. MC cũng điều khiển tài nguyên của hội nghị bằng cách quyết định xem dòng

âm thanh hình ảnh nào sẽ truyền theo dạng multicast.

MC không giải quyết trực tiếp với dòng truyền nào. Đó dành cho MP, nó pha

trộn, chuyển và xử lý âm thanh hình ảnh hay bit dữ liệu. Khả năng MC, MP có thể có

trong các thành phần dành riêng hay một phần của những thành phần H.323 khác.

178

4.2.5 Hội thảo đa điểm:

Khả năng của hội thảo đa điểm có thể được giải quyết bằng được sử dụng

trong nhiều phương pháp và cấu hình khác nhau khi dùng H.323.

4.2.5.1 Hội thảo đa điểm tập trung:

Yêu cầu có sự tồn tại của MCU để làm cho hội thảo đa điểm được dễ dàng.

Tất cả các terminal gởi âm thanh, hình ảnh, dữ liệu và dòng điều khiển đến MCU dưới

dạng điểm nối điểm. MCU tập trung quản lý hội thảo sử dụng chức năng điều khiển

H.245- định nghĩa khả năng của mỗi terminal. MP thực hiện các chức năng xử lý âm

thanh, phân tán dữ liệu, xử lý/chuyển đổi video trong các hội thảo đa điểm và gửi dòng

kết quả lại cho các terminal. MP cũng cung cấp sự chuyển đổi giữa hai loại codec và tỷ

lệ khác nhau, và cũng có thể sử dụng multicast để phân tán hình ảnh video đã được xử

lý. Một MCU đặc thù hỗ trợ hội thảo đa điểm tập trung thường gồm một MC, âm

thanh, hình ảnh, và/hay dữ liệu MP.

4.2.5.2 Hội thảo đa điểm phân tán:

Có thể sử dụng kỹ thuật multicast. Những terminal tham gia vào H.323 sẽ

multicast âm thanh và hình ảnh đến những terminal khác mà không cần gởi dữ liệu đến

một MCU. Chú ý rằng việc điều khiển dữ liệu đa điểm vẫn được xử lý tập trung bởi

MCU, và thông tin kênh điều khiển H.245 vẫn được truyền đến một MC dưới dạng

điểm nối điểm.

Terminal nhận chịu trách nhiệm cho việc xử lý nhiều dòng âm thanh, hình ảnh

đến. Terminal sử dụng kênh điều khiển H.245 để chỉ cho MC có bao nhiêu dòng âm

thanh và hình ảnh cùng lúc có thể giải mã. Số lượng những khả năng cùng lúc của một

terminal không hạn chế số dòng âm thanh hay hình ảnh được multicast trong hội thảo.

MP cũng có thể cung cấp sự chọn lựa hình ảnh hay pha trộn âm thanh trong hội thảo đa

điểm phân tán.

179

4.2.5.3 Hội thảo đa điểm kết hợp:

Sử dụng sự kết hợp của tập trung và phân tán. Tín hiệu H.245 và dòng âm

thanh hay video được xử lý thông qua các thông điệp điểm nối điểm đến MCU. Tín

hiệu còn lại (âm thanh hay video) được truyền tới các terminal H.323 cùng tham gia

bằng multicast.

Một thuận lợi của hội thảo tập trung là tất cả các terminal H.323 đều hỗ trợ

giao tiếp điểm nối điểm. MCU có thể xuất nhiều unicast đến các thành viên hội thảo và

không cần khả năng đặc biệt nào về mạng. Như một sự lựa chọn, MCU có thể nhận

nhiều unicast, trộn âm thanh và chuyển đổi video, xuất một dòng multicast, duy trì

băng thông mạng.

H.323 cũng hỗ trợ hội thảo đa điểm hỗn tạp - một số terminal ở dạng hội thảo

đa điểm tập trung, số khác ở dạng hội thảo đa điểm phân tán, và một MCU cung cấp

cầu nối cho 2 dạng này. Terminal không biết tính chất hỗn tạp của hội thảo, mà chỉ biết

dạng hội thảo mà nó gửi và nhận.

Bằng cách hỗ trợ cả multicast và unicast, H.323 kết nối công nghệ hiện tại và

tương lai. Multicast giúp dùng băng thông mạng hiệu quả hơn , nhưng gây sự tính toán

cho terminal - phải trộn và chuyển đổi các dòng âm thanh/video nhận được. Hơn nữa,

sự hỗ trợ của multicast cần thiết trong các router và switch.

Một MC có thể định vị trong một Gatekeeper, Gateway, Terminal, hay MCU.

Hình 4-4 Ví dụ Hybrid và Decentralized

180

Xét ví dụ đơn giản, một hội thảo đa điểm được thiết lập giữa 3 client (hình

trên ). Một terminal client (Client B) thực hiện chức năng MC. Tất cả terminal đều có

thể dùng multicast để tham gia vào hội thảo phân tán. Chức năng MP trên mỗi nút sẽ

trộn và trình diễn các tính hiệu âm thanh và hình ảnh cho người dùng. Phương pháp

này làm giảm thiểu nhu cầu về tài nguyên mạng. Tuy nhiên, mạng phải được cấu hình

hỗ trợ multicast.

Một MCU riêng có thể được dùng chỉ để xử lý các chức năng audio, dữ liệu và

điều khiển. Trong cấu hình này video vẫn được multicast, nhằm duy trì băng thông.

MCU này có thể là một hệ thống chuyên môn hay một terminal có mã lực mạnh

Hội thảo đa điểm kết nối các terminal trong LAN và không mạng rất có ích

cho các cấu hình mà chức năng MCU được tích hợp chặt chẽ với Gateway.

4.2.6

H.225 Registration, Admission, and Status

4.2.6.1 H.225 tín hiệu gọi :

Tín hiệu gọi H.225 được dùng để thiết lập kết nối giữa các điểm cuối H.323

(terminal và gateway), phục vụ cho vận chuyển dữ liệu thời gian thực. Call signaling

liên quan đến sự trao đổi các thông điệp giao thức H.225 trên một kênh call-signaling.

Ví dụ, các thông điệp giao thức H.225 dùng TCP trong mạng H.323 dựa trên IP.

Các thông điệp H.225 được trao đổi giữa các điểm cuối nếu không có

gatekeeper trong mạng H.323. Khi một gatekeeper tồn tại trong mạng, các thông điệp

H.225 được trao đổi hoặc trực tiếp giữa các endpoint hoặc giữa các endpoint sau khi

được truyền qua gatekeeper. Phương pháp thứ nhất là call signaling trực tiếp. Phương

pháp thứ hai gọi là call signaling truyền qua gatekeeper. Gatekeeper sẽ quyết định

phương pháp nào trong quá trình trao đổi thông điệp về quyền RAS-admission.

181

4.2.6.2

Tín hiệu gọi dẫn đường Gatekeeper:

Các thông điệp chấp nhận được trao đổi giữa các điểm cuối và gatekeeper

trên các kênh RAS. Gatekeeper nhận các thông điệp tín hiệu gọi trên kênh tín hiệu gọi

từ một điểm cuối và truyền chúng đến điểm cuối khác trên kênh tín hiệu gọi của điểm

cuối khác đó.

4.2.6.3

Tín hiệu gọi trực tiếp:

Trong khi xác nhận việc thu nhận, gatekeeper xác định rằng các điểm cuối có

thể trao đổi các thông điệp call-signaling trực tiếp. Các điểm cuối trao đổi call-

signaling trên kênh call-signaling.

4.2.6.4

Tín hiệu điều khiển H.245:

Tín hiệu điều khiển H.245 gồm sự trao đổi của các thông điệp H.245 cuối-

nối-cuối giữa các điểm cuối H.323 giao tiếp. Các thông điệp điều khiển H.245 được

truyền trên các kênh điều khiển H.245. Kênh điều khiển H.245 là kênh logic 0 và được

mở hoàn toàn, không giống các kênh truyền thông. Các thông điệp truyền gồm các

thông điệp trao đổi khả năng của các terminal, các thông điệp đóng và mở kênh logic.

4.2.6.5

Trao đổi khả năng:

Trao đổi khả năng là một tiến trình dùng các thông điệp trao đổi của các

terminal giao tiếp để cung cấp các khả năng truyền nhận của chúng đối với các điểm

cuối tương ứng. Khả năng truyền miêu tả khả năng của terminal để truyền dòng truyền

thông. Khả năng nhận miêu tả khả năng của terminal để nhận và xử lý các dòng truyền

thông đến.

4.2.6.6

Tín hiệu kênh luận lý:

Một kênh logic mang thông tin từ một điểm cuối đến một điểm cuối khác

(trong trường hợp hội thảo điểm-nối-điểm) hay nhiều điểm cuối (trong trường hợp hội

182

thảo điểm-nối-nhiều điểm). H.245 cung cấp các thông điệp để mở hay đóng một kênh

logic; một kênh giao tiếp chỉ có một hướng.

4.2.7 Tín hiệu gọi H.225 và tín hiệu điều khiển H.245:

Ví dụ mạng đơn giản chứa hai thiết bị đầu cuối H.323( T1 và T2)kết nối với

gatekeeper. Giả sử dùng tín hiệu gọi trực tiếp. Cũng giả sử rằng dòng truyền sử dụng

kiểu đóng gói RTP. Hình dưới mô tả cách thức thiết lập cuộc gọi H.323

Hình 4-5 Thiết lập cuộc gọi H323

1. T1 gởi thông điệp RAS ARQ trên kênh RAS đến gatekeeper để đăng ký. T1

đòi hỏi sử dụng tín hiệu gọi trực tiếp.

2. Gatekeeper các nhận lại quyền của T1 bằng cách gởi ACF đến T1.

Gatekeeper chỉ đỉnh trong ACF là T1 có thể sử dụng tín hiệu gọi trực tiếp.

183

3. T1 gởi thông điệp thiết lập tín hiệu gọi H.225 đến T2 yêu cầu kết nối.

4. T2 hồi đáp lại với một thông điệp xử lý cuộc gọi H.225 đến T1

5. Bây giờ T2 phải đăng ký với gatekeeper. Nó gởi thông điệp RAS ARQ đến

gatekeeper trên kênh RAS.

6. Gatekeeper xác nhận đăng ký bằng cách gởi thông điệp RAS ARQ đến T2

7. T2 thông báo cho T2 về việc thiết lập kết nối bằng cách hởi thông điệp cảnh

báo H.225

8. Sau đó T2 xác nhận lại việc thiết lập kết nối bằng cách gợi thông điệp kết nối

đến T1, và cuộc gọi được thực hiện.

Dòng tín hiệu điều khiển H.323

184

9. Kênh điều khiển H.225 được thiết lập giữa T1 và T2. T1 gởi một thông điệp

H.245 TerminalCapbabilitySet đến T2 để trao đổi khả năng của nó.

10. T2 báo nhận những khả năng của T1 bằng cách gởi thông điệp H.245

Terminal CapabilitySetAck

11. T2 trao đổi khả năng của nó với T1 bằng cách gởi thông điệp H.245

TerminalCapabititySet

12. T1 báo nhận những khả năng của T2 bằng cách gởi thông điệp H.245

Terminal CapabilitySetAck

thông điệp H.245

13. T1 mở kênh

truyền với T2 bằng cách gởi

openLogicalChannel. Địa chỉ vận chuyển của kêng RTCP được bao gồm trong

thông điệp.

14. T2 báo nhận sự thiết lập kênh luận lý một chiều từ T1 đến T2 bằng cách gởi

thông điệp H.245 openLogicalChannelAck. Bao gồm trong thông điệp báo nhận

là địa chỉ vận chuyển của RTP cung cấp nởi T2 để cho T1 sử dụng cho việc gởi

dòng truyền thông RTP và địa chỉ RTCP nhận từ T1 sớm hơn

15. Sau đó T2 mở kênh truyền với T1 bằng cách gởi thông điệp H.245

openLogicalChannel. Địa chỉ vận chuyển của kênh RTCP được bao gồm trong

thông điệp

16. T2 báo nhận sự thiết lập của kênh luận lý một chiều từ T2 đến T1 bằng cách

gởi thông điệp H.245 openLogicalChannelAck. Bao gồm trong thông điệp báo

nhận là địa chỉ vận chuyển của RTP cung cấp bởi T1 để cho T2 sử dụng cho

việc gởi dòng truyền thông RTP và địa chỉ RTCP nhận từ T2 sớm hơn.

Bây giờ giao tiếp dòng hai chiều được thiết lập

185

Hình 4-6 H.323 Media Stream and Media Control Flows

17. T1 gởi dòng truyền thông đóng gói theo RTP đến T2

18. T2 gởi dòng truyền thông đóng gói theo RTP đến T1

19. T1 gởi thông điệp RTCP đến T2

20. T2 gởi thông điệp RTCP đến T1

186

Hình 4-7 Giải phóng cuộc gọi

21. T2 bắt đầu giải phóng cuộc gọi. Nó gởi thông điệp kết thúc phiên làm việc

đến T1.

22. T1 giải phóng điểm cuối ở cuộc gọi và xác nhận sự giải phóng bằng cách

gởi thông điệp kết thúc phiên làm việc đến T2.

23. T2 hoàn thành việc giải phóng cuộc gọi bằng cách gởi thông điệp giải phóng

hoàn toàn H.225 đến T1

24. T1 và T2 thoát ra khỏi gatekeeper bằng cách gởi thông điệp RAS DRQ đến

gatekeeper

25. Gatekeeper cũng thoát ra khỏi T1 và T2 và xác nhận bằng cách gởi thông

điệp DCF đến T1 và T2

187

4.2.8 Nghiên cứu thư viện Objective Open H.323 for C

4.2.8.1 Kiến trúc :

Objective Open H.323 for C được xem là một ứng dụng đơn giản, một tiến

trình. Nó cho phép một điểm cuối H.323 đơn lẻ được thiết lập kết nối thông qua kêng

truyền và tín hiệu H.323. Trộn tín hiệu vào ra được thực hiện bằng lệnh Select hay Poll

của Unix để theo dõi tất cả các kênh vào ra đang hoạt động. Giao tiếp TCP/IP và UDP

được hỗ trợ.

Chương trình ứng dụng với ngăn xếp được thực hiện thông qua các hàm

quay lui. Ngăn xếp được thiết kế theo hướng sự kiện và sẽ hồi đáp lại dòng vào ra hay

theo sự kiện thời gian bởi các hàm quay lui đã đăng ký được gọi lại. Những hàm quay

lui được định nghĩa bởi nhiều loại thông điệp Q.931/H.225 khác nhau.

Thôngđiệp Q.931/H.225

Hàm quay lui

Mô tả

Xảy ra khi thông điệp setup

được nhận, hay nếu RAS

được bật lên, khi

gatekeeper chấp nhận yêu

Setup

onIncomingCall

cầu thiết lập cuộc gọi

Hàm quay lui này được gọi

thông sau khi thông điệp

Setup

onOutcomingCall

thiết lập Q.931 được gởi

Xảy ra khi thông điệp cảnh

Alert

onAlerting

giác Q.931 được nhận

Xảy ra khi thông điệp kết

nối Q.931 được nhận. Nó

không xảy ra cho tới sau

khi thông đệp tạo đường đi

H.245 trong thông điệp kết

nối được xử lý

Connect

onCallEstablished

Facility

Xử lý bên trong. Thông

188

điệp H.245 tạo đường ống

hay yêu cầu bắt đầu H.245

được xử lý

Xảy ra khi thông điệp giải

phóng hoàng toàn Q.931

ReleaseComplete

onCallClear

được nhận

Information

Notify

Progress

Status

Không có hành động nào

Status Enquiry

được thực hiện trên các

SetupAck

thông điệp này

Chương trình ứng dụng H.323 sử dụng giao tiếp đồng đẳng cho việc trao đổi

dữ liệu. Điều này có nghĩa là bất cứ ứng dụng nào cũng đóng hai vai trò vừa là client,

vừa là server. Đây là ứng dụng gọi điện đơn giản dựa trên H.323 mô tả khả năng thiết

lập cuộc gọi, thương lưởng về khả năng và bắt đầu kênh truyền âm thanh.

4.2.8.2 Mẫu thiết kế ứng dụng H.323 đơn giản:

4.2.8.2.1 Khởi tạo điểm cuối:

Trước khi ngăn xếp ooh323c có thể làm mọi việc, cấu trúc điểm cuối phải

được khởi tạo. Nó được thu65c hiện bằng cách gọi các hàm sau:

ooH323EpInitialize(args…)

Tham số bao gồm thông tin về định danh người gọi, loại cuộc gọi được thực

hiện( âm thanh, hình ảnh, hay fax) và tên tập tin lưu vết đường đi, chỗ mà thông tin bản

ghi được lưu trữ.

Những thuộc tính khác có thể được thiết lập thông qua một loạt các cuộc

gọi hàm ooH323EpSet. Những thuộc tính được thiết lập này trong đối tượng điểm cuối

toàn cục. Ví dụ:

189

ooH323EpSetAliasH323ID : có thể được sử dụng để thiết lập định

danh trong địa chỉ bí danh.

Việc sử dụng dịch vụ client gatekeeper RAS – “Registration,

Admission, and Status” nên được khởi tạo thông qua việc gọi hàm sau :

ooGkClientInit(eGkMode, szGkAddr, iGkPort)

Đối với những cuộc gọi điểm nối điểm đơn giản, thông số chế độ

gatekeeper nên được thiết lập là RasNoGatekeeper và tất cả các thông số nên được

thiết lập là 0. Các chế độ Gatekeeper khác là RasDiscoverGatekeeper( khám phá một

gatekeeper) hay là RasUseSpecificGatekeeper( sử dụng gatekeeper xác định). Các

thông số khác được sử dụng để thiết lập địa chỉ Ip và số Port

4.2.8.2.2

Thêm vào khả năng:

Một ứng dụng H.323 phải xác định cho máy khách của nó biết nó có khả

năng làm cái gì. Thương lượng về khả năng sẽ được diễn ra bên trong việc xử ý thông

điệp H.245 để đạt đến sự đồng ý lẫn nhau dựa trên tập các khả năng.

Những khả năng được xác định dựa trên một loạt các hàm sau đây:

ooAddCapability(capability, type, callbacks);

giá trị tham số capabitity được định nghĩa trong ooCapability.h. Đây là

những hằng số định nghĩa lọai khả năng đã biết. Người sử dụng có thể ở rộng danh

sách này nếu muốn chương trình hỗ trợ những khả năng không có trong danh sách.

Tham số type xác định lọai khả năng được định nghĩa trong

MULTIMEDIA_SYSTEM_CONTROL.h

Có nhiều loại hàm quay lui khác nhau được thực hiện khi kênh luận lý

được mở hay đóng. Những hàm quay lui được xác định ở đây:

startReceiveChannel

startTransmitChannel

stopReceiveChannel

190

stopTransmitChannel

4.2.8.2.3 Định nghĩa hàm quay lui:

Khi các điểm cuối được thiết lập, người dùng đăng ký các hàm quay lui mà họ

định nghĩa. Hàm quay lui được định nghĩa ở cả mức độ H.245 khi kênh luận lý được

mở hay đóng hay ở mức độ Q.931/H.225 khi những thông điệp tín hiệu được trao đổi.

Ngăn xếp sẽ thực thi những hàm này khi sự kiện gắn với hàm quay lui đó xảy ra.

Các hàm quay lui Q.931/H.225 được đăng ký bằng cách gọi những hàm sau:

ooH323EpRegisterCallbacks

Ít nhất thì người dùng phải thực thi những hàm quay lui khả năng để bắt đầu

và kết thúc dòng truyền cho ứng dụng đặc biết của họ. Bắt đầu hay kết thúc dòng

truyền không được hỗ trợ trong ooH323c

4.2.8.2.4 Tạo H.323 Listener:

Một H.323 Listener được tạo để chấp nhận các yêu cầu kết nối vào. Tất cả mọi

thứ để bắt đầu listener là gọi hàm sau:

ooCreateH.323Listener();

4.2.8.2.5 Khởi tạo cuộc gọi:

Dùng để mở kênh truyền cho bất cứ loại giao tiếp truyền thông nào – không

chỉ là âm thanh. Một cuộc gọi được khởi tạo để gởi hình ảnh hay dữ liệu. Hàm

ooMakeCall (dest, callToken, bufsiz) được sử dụng cho mục đích này.

4.2.8.2.6 Đóng một cuộc gọi:

Mỗi bên kết nối đều có thể đóng cuộc gọi. Gọi hàm :

ooHangCall(callToken)

4.2.8.2.7 Đóng ngăn xếp:

191

Gọi hàm ooStopMonitor để đóng ngăn xếp. Nó sẽ gọi

làm hàm

ooMonitorChannel thoát. Khi điều này xảy ra, người dùng sẽ gọi hàm ooH323Destroy

ở cuối chương trình dọn dẹp điểm cuối

4.3

Windows Media Encoder

4.3.1 Windows Media Encoder:

Windows Media Encoder SDK (Software Developement Kit) là một trong

những thành phần chính của Microsoft Windows Media 9 Series. Những phần khác

gồm:

• Microsoft Windows Media Services 9 Series SDK

• Microsoft Windows Media Format 9 Series SDK

• Microsoft Windows Media Rights Manager 9 Series SDK

• Microsoft Windows Media Player 9 Series SDK

• Windows Media 9 Series Embedded Product Adaptation Kit (PAK)

Windows Media Encoder SDK được thiết kế cho những ai muốn phát triển một

ứng dụng Windows Media Encoder bằng cách dùng các hàm API (application

proramming interface – giao diện lập trình ứng dụng) tự động hóa cao. Với SDK này,

một lập trình viên dùng C++, Microsoft Visual Basic, hay một ngôn ngữ dạng kịch bản

có thể bắt các nội dung đa truyền thông và mã hóa và các tập tin hay dòng (stream)

dạng Windows Media. Chẳng hạn, bạn có thể dùng API tự động hóa này để :

o Broadcast content trực tuyến: một tổ chức truyền tin có thể dùng API tự động

hóa để lên lịch chụp tự động và broadcast nội dung. Các ngành vận chuyển địa

phương có thể dẫn dòng các ảnh động của điều kiện đường ở những điểm gây

nguy hiểm, cảnh báo tài xế về tình trạng kẹt xe và khuyến cáo dùng những con

đường khác.

192

o Batch-process nội dung : một tổ chức sản xuất truyền thông phải xử lý một số

lượng lớn các tập tin, có thể cần tạo tiến trình chạy nền dùng API tự động hóa

để bắt mã hóa dòng lặp đi lặp lại, cái này sau cái khác. Một tập đoàn có thể

dùng API tự động hóa để xử lý các dịch vụ truyền thông theo dòng với ngôn

ngữ kịch bản hay dùng và Windows Script Host. Windows Script Host là máy

chủ độc lập ngôn ngữ có thể dùng để chạy bất kỳ các engine kịch bản trên

Windows 95 hay sau đó, Windows NT, hay Windows 2000.

o Tạo giao diện người dùng tùy biến : một nhà cung cấp dịch vụ Internet có thể

xây dựng một giao diện dùng chức năng của API tự động hóa để chụp, mã hóa,

và broadcast dòng truyền thông. Thay vào đó, ta có thể dùng các giao diện định

nghĩa trước dành cho người dùng trong API tự động hóa với cùng mục đích.

o Quản trị từ xa các ứng dụng Windows Media Encoder: ta có thể dùng API

tự động hóa để chạy, sửa lỗi và quản trị các ứng dụng Windows Media Encoder

từ máy ở xa.

Tài liệu này cung cấp cái nhìn tổng quan về các đề tài mã hóa chung, hướng dẫn

lập trình, và các tham chiếu đầy đủ về các giao diện, đối tượng, kiểu liệt kê, cấu trúc và

hằng, đi kèm là các ví dụ.

4.3.1.1 Tìm hiểu Windows Media Encoder SDK :

Windows Media Encoder SDK mạnh mẽ và đáng tin cậy, cung cấp một tập

phong phú về giao diện cho phép các lập trình viên tích hợp Windows Media vào trong

các ứng dụng và dòng công việc. Windows Media Encoder SDK hỗ trợ nhiều ngôn ngữ

lập trình gồm C++, Visual Basic, Visual Basic Scripting Edition (VBScript), Visual

Basic cho ứng dụng, và tất cả các ngôn ngữ lập trình thuộc bộ Microsoft .NET. Nhiều

ứng dụng khác nhau có thể phát triển dùng Windows Media Encoder SDK, chẳng hạn

video e-mail, các thu thập giám sát bảo mật, bộ mã hóa dạng nền, công cụ chụp màn

hình, các add-ins Microsoft PowerPoint® and Microsoft Office, các bộ thâu số, các

193

ứng dụng mã hóa tùy biến. Chẳng hạn, phần mềm Windows Media Encoder phát triển

dựa trên Windows Media Encoder SDK.

Windows Media Encoder SDK cung cấp một tập các tính năng rộng lớn, cho

phép người dùng thực hiện:

o Mã hóa nhiều định dạng tập tin khác nhau.

o Xem dữ liệu đầu vào và đầu ra của nội dung trong khi xử lý mã hóa.

o Mã hóa nội dung theo dòng hay theo tập tin. Các dòng có thể kéo từ các ứng

dụng mã hóa hay đẩy lên một server Windows Media.

o Điều khiển các thiết bị số dùng chính các ứng dụng mã hóa.

o Nhận các số liệu thống kê trong quá trình hay sau quá trình mã hóa.

o Tạo và hiệu chỉnh các profile mã hóa tùy biến.

o Chỉnh sửa các dòng bằng cách tạo nhiều tập tin từ một tập tin multiple bit rate

(MBR) đơn, hay bằng cách tạo một tập tin MBR từ nhiều tập tin.

o Chỉnh sửa tập tin Windows Media bằng cách cắt bớt các khỏang bắt đầu và kết

thúc, hay bằng các thêm các dữ liệu meta, kịch bản, đánh dấu, và chỉ mục.

o Bảo vệ nội dung trong suốt quá trình mã hóa dùng công nghệ quản lý chữ ký

số (digital rights management DRM).

Windows Media Encoder SDK xây dựng trên Windows Media Format SDK,

cung cấp các chức năng cấp thấp. Không như Windows Media Format SDK, Windows

Media Encoder SDK hỗ trợ các ngôn ngữ kịch bản và cho phép xây dựng các ứng dụng

phức tạp với rất ít mã thêm vào. Hơn nữa, Windows Media Encoder SDK hỗ trợ nhiều

nguồn dữ liệu và tùy chọn xuất mà không cần người lập trình tự viết các thành phần

cấp thấp này.

4.3.1.2 Tìm hiểu Windows Media Format :

Windows Media Format là một định dạng thuộc chủ quyền cho dẫn dòng âm

thanh, hình ảnh và văn bản từ server Internet đến máy khách. Một tập tin Windows

194

Media có thể lưu trữ và trình diễn cục bộ. Mỗi tập tin Windows Media chứa một hay

nhiều dòng truyền thông để tạo nên một trình diễn đa truyền thông. Phân phối dòng

đồng bộ với dòng thời gian. Các danh sách sau giới thiệu các tính năng chính của

Windows Media Format:

o Một tập tin Windows Media Encoder có thể truyền bằng bất kỳ nghi thức vận

chuyển liên lạc dữ liệu bên dưới. Windows Media Format không chỉ rõ định

dạng về các gói tin dữ liệu cho các nghi thức mạng khác nhau.

o Windows Media Format linh động về băng thông. Một dòng đầu vào đơn có thể

mã hóa thành nhiều dòng đầu ra trong một tập tin Windows Media. Mỗi dòng

tùy biến lại như thế khác nhau ở chỗ tần số bit mà nó có thể dựng hình, và chỉ

một tại một thời điểm. Server Windows Media dùng phân dùng thông minh để

gởi dòng chất lượng cao đến một máy khách phù hợp.

o Phân phối và trình diễn nhiều dòng dữ liệu truyền thông đồng bộ với dòng thời

gian chung. Dữ liệu truyền thông trong một tập tin Windows Media đóng tem

thời gian.

o Một tập tin Windows Media có thể chứa một dòng hình ảnh, một dòng âm

thanh, một dòng Web, và một dòng kịch bản.

o Máy khách không cần lưu trữ nôi dung dựa trên Windows Media để trình diễn

dòng đa truyền thông.

o Windows Media Format xây dựng các điều khiển cấp thấp các thao tác đọc và

viết.

4.3.1.3 So sánh WME SDK và WMF SDK:

Functionality

Windows Media

Windows Media

Encoder SDK

Format SDK

Tự động hóa ứng dụng.

Không

195

Tự động đọc nội dung truyền thông nén

Không

và thô, và nén ghi như nội dung dựa trên

Windows Media.

Có thể chuyển các dòng âm thanh hình

Không

ảnh sang định dạng Windows Media.

Cung cấp giao diện người dùng Windows

Không

Media Encoder tùy chọn.

Cài đặt Profile Manager.

Không

Có thể điều khiển từ xa các ứng dụng

Không

Windows Media Encoder.

Nén dữ liệu đa truyền thông.

Chỉnh sửa thông tin header của tập tin

Windows Media.

Ghi các số liệu thống kê mã hóa.

Giải nén dữ liệu đa truyền thông để chơi

Không

lại.

Lập trình tạo một profile.

Điều khiển thiết bị số bằng lập trình.

Không

Tích hợp thẳng với các dịch vụ tạo nội

Không

dung DRM.

Hỗ trợ ngôn ngữ lập trình.

C,

C++,

C#, C, C++

196

Microsoft Visual

Basic,

Visual

Basic

Scripting Edition,

Microsoft JScript®,

Microsoft Windows

Script Host

Bảng 4-2 So sánh Windows Media Encoder SDK và Windows Media Format

4.3.2 Hệ thống cấp bậc các đối tượng mã hóa:

Windows Media Encoder SDK được xây dựng trên nền Windows Media

Format, một API cấp thấp chứa các giao diện cần cho:

o Ghi các tập tin Windows Media từ các dữ liệu âm thanh, hình ảnh, và kịch bản

chưa nén.

o Đọc và giải nén các tập tin Windows Media.

o Chỉnh sửa thông tin header tập tin Windows Media.

Windows Media Encoder SDK bao gồm một số đối tượng có thể tạo thể hiện

độc lập bằng cách dùng class ID của chúng. Chẳng hạn, tạo đối tượng WMEncoder để

lấy con trỏ tới một giao diện IWMEncoder. Các con trỏ đến các giao diện khác, tuy

nhiên, phải được lấy thông qua những đối tượng khác đã có sẵn. Chẳng hạn, để nhận

giao diện IWMEncBroadcast, ta phải dùng phương thức get_Broadcast trong giao

diện IWMEncoder vì ta không thể dùng CoCreateInstance()để nhận trực tiếp giao

diện IWMEncBroadcast. Sơ đồ sau mô tả quan hệ các đối tượng trong Windows

Media Encoder SDK và những đối tượng nào phụ thuộc đối tượng khác.

197

Hình 4-8 Cấp bậc đối tượng trong Windows Media Encoder SDK

198

Ví dụ C++

// Initialize the COM library.

HRESULT hr = Coinitialize(NULL);

// Create a WMEncoder object and retrieve an

// IWMEncoder interface pointer.

IWMEncoder* pEncoder = NULL;

HRESULT hr = CoCreateInstance( CLSID_WMEncoder,

NULL,

CLSCTX_INPROC_SERVER,

IID_IWMEncoder

(void**) (&pEncoder));

// Create a broadcast interface.

IWMEncBroadcast* pBrdCst = NULL;

hr = pEncoder->get_Broadcast(&pBrdCst);

4.3.2.1 Đóng gói đối tượng:

Các đối tượng và thư viện kiểu Windows Media Encoder SDK được tổ chức

thành các thư viện liên kết động và các tập tin thực thi.

Tên

Mô tả

Mspshell.dll

Chứa giao diện IMSPropShell dùng để tạo các máy chủ chứa

các trang tính năng dùng chung. Windows Media Encoder dùng

IMSPropShell cài đặt các trang tính năng định nghĩa trước của

giao diện người dùng Session Properties.

Streameditor.dll

Chứa giao diện IWMEncStreamEdit dùng để cắt và nối các

199

dòng trong tập tin Windows Media.

Wmdevctl.dll

Chứa các giao diện cần cho điều khiển các thiết bị số và dùng

danh sách quyết định chỉnh sửa (edit decision list EDL).

Wmedque.dll

Chứa bộ lọc hàng đợi bản ghi.

Wmenceng.dll

Chứa các giao diện cần cho cấu hình và thao tác xử lý mã hóa.

Wmencloc.dll

Chứa các giao diện cần cho quản trị các ứng dụng Windows

Media Encoder trên máy tính ở xa.

Wmesrcwp.dll

Chứa bộ bao mã nguồn.

WMEncRes.dll

Chứa các chuỗi tài nguyên của Windows Media Encoder.

Wmex.dll

Chứa các thành phần giao diện người dùng và giao diện

IWMEncProfileManager. Các lớp này là các trang tính năng

định nghĩa sẵn được điều khiển MSPropShell ActiveX dùng

để tạo giao diện người dùng Session Properties.

Wmexfmwp.dll

Chứa bộ bao plug-in chuyển đổi.

Wmexres.dll

Chứa các chuỗi tài nguyên cho các trang tính năng.

Wmprevu.dll

Chứa giao diện IWMEncDataview dùng cho tạo các nội dung

truyền thông xem trước và trong lúc mã hóa.

Wmsservertypelib.dll Chứa thư viện kiểu mô hình đối tượng server, được dùng để lấy

các số liệu thống kê server và họat động với DCOM.

Wmenc.exe

Chạy Windows Media Encoder và trình bày giao diện người

dùng, chứa đối

tượng WMEncoderApp và giao diện

200

IWMEncoderApp.

Wmencagt.exe

Chứa đối tượng WMEncoderAgent dùng để quản trị các ứng

dụng Windows Media Encoder trên máy ở xa.

Bảng 4-3 Các tập tin thư viện liên kết động và thực thi

4.3.2.2 Các tính năng:

4.3.2.2.1 Điều khiển các kết nối đến máy khách:

Điều khiển truy cập đến máy tính đang chạy các ứng dụng Windows Media

Encoder. Một cách để broadcast một dòng là cho phép các máy khách kết nối trực tiếp

máy đang chạy ứng dụng Windows Media Encoder (tính năng kéo). Mặc định, tối đa 5

máy có thể kết nối. Các quản trị viên có thể thay đổi giới hạn này lên cực đại là 50

bằng

cách

chỉnh

trong

khóa

registry

HKEY_CLASSES_ROOT\Software\Microsoft\Windows

Media

Tools\Encoder\MaxClientConnections. Bởi vì mỗi kết nối hao tốn tài nguyên hệ

thống và mạng, cần xem xét lại khả năng máy và môi trường truyền. Quá nhiều kết nối

có thể làm quá tải máy và ngăn cản các máy khách chính đáng kết nối vào.

Ta có thể ngăn cấm máy kết nối bằng cách áp mặt na địa chỉ IP để kết nối máy

khách. Mặc định, bất kỳ máy khách chưa đến giới hạn kết nối đều được cho phép. Mặc

dù Windows Media Encoder SDK không cung cấp sẵn API để làm việc này, ta có thể

dùng Windows Media Format. Để biết thêm thông tin, xem thêm giao diện

IWMAddressAccess và IWMAddressAccess2 trong trợ giúp của Windows Media

Format.

4.3.2.2.2 Dùng DCOM:

Distributed Component Object Model (DCOM – mô hình đối tượng thành phần

phân phối) là một nghi thức cho phép các thành phần phần mềm liên lạc trực tiếp thông

201

qua mạng dùng TCP/IP. DCOM có thể dùng với Windows Media Encoder khi ta đang

quản trị từ xa các máy đang chạy ứng dụng Windows Media Encoder, và trên các

server Windows Media khi ta dùng tính năng đẩy.

4.3.2.3 Tìm hiểu codec:

Nội dung âm thanh và hình ảnh có thể tiêu tốn nhiều băng thông dẫn dòng và

tạo tập tin lớn. Bằng cách nén lại, nó có thể broadcast trên những băng thông Internet

phổ biến và lưu thành tập tin Windows Media với kích thước vừa phải. Ta có thể nén

nội dung bằng cách áp dụng các thuật toán nén cho dữ liệu, dựa vào chất lượng đầu ra

mong muốn và băng thông khả dụng. Trước khi nội dung được trình diễn, nội dung

được giải nén bằng các thuật tóan giải nén.

Những thuật toán nén và giải nén như thế gọi là các codec. Bảng sau cung cấp

thông tin về các codec khả dụng trong Windows Media Encoder Series.

Codec

Description

Windows

Media

Tạo âm thanh full surround trên những máy tính cài đặt card âm

Audio 9 Professional

thanh đa kênh và Windows XP. Cung cấp nội dung âm thanh

trong Windows Media Format để chơi lại trên thiết bị xem như

đầu đĩa DVD hay hộp set-top.

Windows

Media

Cung cấp mã hóa toàn vẹn về âm thanh.

Audio 9 Lossless

Windows

Media

Cung cấp chất lượng âm thanh không gì sánh kịp cho dẫn dòng

Audio 9

băng hẹp Internet và âm nhạc download hi-fi. Hỗ trợ mã hóa

VBR. Tương thíc hòan tòan với mọi phiên bản Windows Media

Player.

Windows

Media Cung cấp chất lượng tốt cho nội dung âm thanh với tiếng nói.

202

Audio 9 Voice

Windows

Media

Tăng cường chất lượng hình ảnh cho người dùng Internet băng

Video 9

rộng và phân phối phim hình gần như DVD với tốc độ lên đến

400 Kbps. Cho phép chơi lại chất lượng sắc nét hơn bằng cách

kết hợp nội dung trên TV và hộp set-top.

Windows

Media

Hỗ trợ nhiều loại băng thông mạng. Giảm việc trùng lắp nội

Video 8.1

dung trước khi mã hóa.

Windows

Media

Cho phép người dùng Windows Media Player 7 xem các nội

Video 7

dung phim hình đã mã hóa mà không cần phải download về bộ

codec mới nhất. Lựa chọn tốt nhất cho những máy tính không

thể hỗ trợ những yêu cầu trình diễn của các codec mới nhất.

Windows

Media

Cung cấp cải thiện xử lý các hình bóng, chuyển động trên màn

Video 9 Screen

hình, và cuộn cho chụp màn hình. Hỗ trợ CBR và VBR một

bước mã hóa mà không rớt khung. Codec này thì tối ưu hóa

hòan toàn cho cả kịch bản dẫn dòng và download.

Bảng 4-4 Các codec

4.3.2.4 Các yêu cầu về tính năng:

Các tính năng.

Feature

Windows Media Player

Operating

Codec

system

6.4 7.1/Windows® XP 9

Series

203

Interlaced output

X

Microsoft

Windows Media

Windows XP

Video 9

video

X

Nonsquare pixel

output

X

Multiple-

resolution MBR

content

X

DRM support

X X

X

Multichannel

Microsoft

Windows Media

audio

Windows XP

Audio

9

Professional

X

Microsoft

Windows Media

High-resolution

Windows XP

Audio

9

audio (24-bit, 96

Professional

kHz)

Dynamic

range

X

Microsoft

Windows Media

control

Windows XP

Audio

9

Professional

X X

X

See

the

CBR

encoding

following

(one- or

two-

table.

pass)

Quality

based

X

X

See

the

VBR

following

table.

204

Bit

rate-based

X

X

See

the

VBR

following

table.

Peak bit

rate-

X

X

See

the

based VBR

following

table.

Bảng 4-5 Các tính năng

Bảng tiếp theo này ghi những phương thức mã hóa cho các codec.

Quality

Bit

rate-

Peak bit rate-

Two-

Codec

One-

based VBR

based VBR

based VBR

pass

pass

CBR

CBR

Windows Media

Audio

9

Professional

Windows Media

Không

Không

Không

Không

Audio

9

Lossless

Windows Media

Audio 9

Windows Media

Không

Không

Không

Không

Audio 9 Voice

Windows Media Có

205

Video 9

Windows Media

Video 8.1

Windows Media

Video 7

Windows Media

Không

Không

Không

Video 9 Screen

Bảng 4-6 Các phương thức mã hóa hỗ trợ

4.3.2.5 Phần mở rộng của tập tin:

Phần mở rộng của tập tin cung cấp thông tin về nội dung chứa trong tập tin:

o Các ứng dụng tạo ra các tập tin Windows Media chứa dòng âm thanh, dòng kịch

bản hay cả hai phải dùng phần mở rộng .wma.

o Các ứng dụng tạo ra các tập tin Windows Media chứa cả dòng hình ảnh, dòng

âm thanh phải dùng phần mở rộng .wmv. Các tập tin này cũng chứa dòng kịch

bản.

o Tập tin chứa cấu hình Windows Media Encoder định nghĩa trước phải dùng

phần mở rộng .wme.

o Profile dùng phần mở rộng .prx.

Chú ý:

Ta có thể dùng phần mở rộng .asf đổi chỗ qua lại với .wmv và .wma, tuy nhiên,

.wmv và .wma xác định loại nội dung.

4.3.2.6 Lập trình bằng C++:

Chủ đề này nói những lưu ý về lập trình trong C++. Nếu không nói rõ, các ví dụ

về sau sử dụng Microsoft Visual C++® 6.0. Từ đây trở đi, tuy ta chú trọng vào lập

206

trình bằng C++. C++ khá linh động trong viết mã nhưng bù lại, thảo chương khá dài và

yêu cầu cẩn thận cao hơn so với VB và C#.

Khi lập trình trong C++, ta phải theo các tập tin tiêu đề cần thiết vào project:

Tập tin tiêu đề Mô tả

localagent.h

Các giao diện cho phép quản trị từ xa với các ứng dụng Windows

Media Encoder.

mspropshell.h Các giao diện cho phép cài đặt các hộp thoại chứa các trang tính

năng định nghĩa sẵn.

wmdevctl.h

Các giao diện cho điều khiển thiết bị số.

wmdrmprf.h

Các giao diện cho bảo vệ nội dung với DRM.

wmencode.h

Các giao diện dùng để cấu hình và chạy các ứng dụng Windows

Media Encoder.

wmencvu.h

Giao diện được dùng để tạo và chạy phần xem trước của dòng.

wmsencid.h

Một tập hòan chỉnh các định nghĩa DISPID.

Bảng 4-7 Các tập tin tiêu đề

Thay vì thêm các tập tin tiêu đề wmencode.h và mspropshell.h, ta có thể sử

dụng các thư viện phát sinh các lớp bao để đơn giản hóa các giao diện COM liên quan:

#import "WMEnc.exe"

#import "MSPShell.dll"

4.3.2.7 Tạo ứng dụng mã hóa:

Để tạo một ứng dụng mã hóa, ta thường trải qua các bước sau:

207

1. Tạo một đối tượng Encoder.

2. Tạo một nhóm nguồn để giữ các dòng đa truyền thông ta muốn mã hóa, và sau

đó thêm các dòng đa truyền thông (chẳng hạn, một tập tin hay dữ liệu đầu vào

từ card chụp màn hình) vào nhóm nguồn.

3. Chọn profile mã hóa. Một profile cho biết loại codec nào được dùng để mã hóa

nội dung và xác định số lượng và tốc độ bit của dòng xuất.

4. Xác định nhu cầu muốn broadcast nội dung đã mã hóa thành dòng, lưu vào tập

tin, hay cả hai.

5. Tùy chọn, ta cũng có thể:

o Thêm thông tin mô tả (như tựa và bản quyền) và các thuộc tính tùy biến.

o Xử lý trước phim hình, chẳng hạn lọc và xén lại, hay xác định các thiết lập

tối ưu hóa.

o Thêm họa tiết.

o Bảo vệ nội dung bằng cách mật mã hóa với DRM.

6. Khởi động mã hóa.

4.3.2.7.1 Tạo đối tượng Encoder:

Tùy thuộc vào ta tạo giao diện người dùng (UI) như thế nào:

o Khi dùng UI tùy biến, tạo một đối tượng WMEncoder trực tiếp bằng cách dùng

giao diện IWMEncoder trong C++.

o Khi thể hiện các thành phần UI định nghĩa sẵn từ Windows Media Encoder, lấy

đối tượng WMEncoder từ WMEncoderApp hay IWMEncoderApp. Đối

tượng WMEncoderApp phải có phạm vi module tồn tại bên ngoài thủ tục.

4.3.2.7.2 Tạo đối tượng WMEncoder với giao diện tùy biến:

Ví dụ C++

// Include libraries.

#include

208

#include "wmencode.h"

// Declare variables.

HRESULT hr = S_OK;

IWMEncoder* pEncoder = NULL;

// Initialize the COM library and retrieve a pointer

// to an IWMEncoder interface.

hr = CoInitialize(NULL);

if ( SUCCEEDED( hr ) )

{

hr = CoCreateInstance(CLSID_WMEncoder,

NULL,

CLSCTX_INPROC_SERVER,

IID_IWMEncoder,

(void**) &pEncoder;

}

// Release pointers.

if ( pEncoder )

{

pEncoder->Release();

pEncoder = NULL;

}

4.3.2.7.3 Tạo đối tượng WMEncoder khi hiển thị giao diện người

dùng ứng dụng định nghĩa sẵn:

209

Ví dụ C++

// Include libraries.

#include

#include "wmencode.h"

// Declare variables.

HRESULT hr;

IWMEncoder* pEncoder;

IWMEncoderApp* pEncoderApp;

// Initialize the COM library and retrieve a pointer

// to an IWMEncoderApp interface.

hr = CoInitialize(NULL);

if ( SUCCEEDED( hr ) )

{

hr = CoCreateInstance( CLSID_WMEncoderApp,

NULL,

CLSCTX_LOCAL_SERVER,

IID_IWMEncoderApp,

(void**) &pEncoderApp);

}

// Display the user interface.

if ( SUCCEEDED( hr ) )

{

hr = pEncoderApp->put_Visible(VARIANT_TRUE);

}

// Acquire an IWMEncoder interface.

if ( SUCCEEDED( hr ) )

210

{

hr = pEncoderApp->get_Encoder(&pEncoder);

}

// Release pointers.

if ( pEncoder )

{

pEncoder->Release();

pEncoder = NULL;

}

if ( pEncoderApp )

{

pEncoderApp->Release();

pEncoderApp = NULL;

}

4.3.2.7.4 Thao tác trên các nguồn và nhóm nguồn:

Windows Media Encoder SDK dùng khái niêm “nguồn” và “nhóm nguồn” để

xác định các dòng nhập ta muốn mã hóa:

o Một nguồn là một dòng âm thanh, dòng hình ảnh, dòng HTML, hay dòng kịch

bản.

o Một nhóm nguồn là một sưu tập các nguồn bao gồm tổ hợp bất kỳ của một

nguồn âm thanh, một nguồn hình ảnh, một nguồn HTML, và một nguồn kịch

bản.

Chẳng hạn, để mã hóa một buổi hòa nhạc sống, ta sẽ thiết lập một nhóm nguồn

gồm một nguồn âm thanh và một nguồn hình ảnh. Để mã hóa trình diễn PowerPoint, ta

211

phải thiết lập một nhóm nguồn gồm một nguồn âm thanh, một nguồn hình ảnh và một

nguồn HTML.

Ta có thể thiết lập nhiều nhóm nguồn trong một session mã hóa để mã hóa đồng

thời các nội dung khác nhau. Chẳng hạn, để broadcast một buổi họp công ty trực tuyến,

ta sẽ thiết lập bốn nhóm nguồn tương ứng với sự kiện chính, phim hình chào mừng,

phim hình lúc ngừng, và phim hình lúc bế mạc.

Hình 4-9 Mô tả 4 nhóm nguồn

Chỉ một nhóm nguồn có thể họat động tại một thời điểm; ta có thể hoặc đặt một

nhóm nguồn hoạt động, hay có các nhóm nguồn xoay dần theo thứ tự khi cái đầu tiên

kết thúc mã hóa.

Xác định các nguồn cho một session mã hóa theo các bước sau:

1. Tạo một

sưu

tập nhóm nguồn để giữ các nhóm nguồn dùng

IWMEncSourceGroupCollection.

2. Tạo một nhóm nguồn để giữ một hay nhiều nguồn đầu vào dùng

IWMEncSourceGroup.

212

3. Tạo các đối tượng cho các nguồn đầu vào và thêm chúng vào nhóm nguồn dùng

IWMEncSource.

4. Dùng IWMEncSource, cho biết loại nguồn đầu vào. Nếu nguồn là một thiết bị

(chẳng hạn là card bắt hình hay máy quay phim DV), trước hết ta phải liệt kê số

nguồn

khả

dụng

trên

hệ

thống

dùng

IWMEncPluginInfo,

IWMEncSourcePluginInfoManager,

IWMEncDeviceControlPluginInfoManager.

Ở đây, ta sẽ xem xét kỹ chủ đề : “Dùng chụp màn hình như là nguồn”, cho biết

làm cách nào dùng chụp màn hình như một nguồn hình ảnh.

Dùng chụp màn hình như một nguồn

Ta có thể dùng chụp màn hình như một nguồn hình ảnh. Plug-in chụp màn hình

cho phép bắt hình ở mọi phần của màn hình, chẳng hạn, để bắt di chuyển của mouse để

mô tả một quá trình. Ta cũng có thể chụp từ một card nối đến thiết bị chuyển đổi quét.

Ta cần cấu hình plug-in để xác định khu vực ta muốn chụp. Một cách là dùng

giao diện IPropertyBag (xem ví dụ C++ ở dưới).

Cân nhắc các tham khảo sau để cải thiện việc chụp màn hình:

o Dùng Windows Media Video 9 codec.

o Dùng card đồ họa nhanh hơn.

o Dùng máy tính cấu hình mạnh hay máy tính với bộ đôi vi xử lý.

o Vô hiệu hóa tăng tốc phần cứng. Từ Control Panel Display Properties, và tab

Settings, click Advanced. Trên tab Troubleshoot, kéo slide thiết lập tăng tốc

phần cứng về None.

o Giảm chất lượng màu để giảm số lượng dữ liệu mà card đồ họa cần xử lý. Từ

Control Panel Display Properties, trên tab Settings, click thiết lập thấp hơn cho

Color quality.

o Chạy ứng dụng mã hóa trong 256 màu. Right-click tập tin thực thi, chọn

Properties, và trên tab Compatibility, chọn Run in 256 colors.

213

o Chỉnh sửa profile để giảm tốc độ khung và kích thước bắt ảnh. Tăng cường tần

suất bit cũng cho kết quả tốt hơn.

o Đóng hết những ứng dụng không cần thiết.

o Bỏ ảnh nền.

Ví dụ Visual Basic sau mô tả việc dùng chụp màn hình như là một nguồn. Ví dụ

C++ mô tả cấu hình chụp màn hình dùng property bag.

Ví dụ C++

// Include libraries.

#include

#include

#include

#include "C:\WMSDK\WMEncSDK9\include\wmencode.h"

// Define the screen capture properties.

#define WMSCRNCAP_CAPTUREWINDOW CComBSTR("CaptureWindow")

#define WMSCRNCAP_WINDOWLEFT CComBSTR("Left")

#define WMSCRNCAP_WINDOWTOP CComBSTR("Top")

#define WMSCRNCAP_WINDOWRIGHT CComBSTR("Right")

#define WMSCRNCAP_WINDOWBOTTOM CComBSTR("Bottom")

#define WMSCRNCAP_FLASHRECT CComBSTR("FlashRect")

#define WMSCRNCAP_ENTIRESCREEN CComBSTR("Screen")

#define WMSCRNCAP_WINDOWTITLE CComBSTR("WindowTitle")

// Declare variables.

HRESULT hr = S_OK;

IWMEncoder* pEncoder;

IWMEncSourceGroupCollection* pSrcGrpColl;

214

IWMEncSourceGroup* pSrcGrp;

IWMEncSource* pSrc;

IWMEncVideoSource2* pSrcVid;

IPropertyBag* pPropertyBag;

CComVariant varValue;

// Initialize the COM library and retrieve a pointer to an IWMEncoder interface.

hr = CoInitialize(NULL);

if ( SUCCEEDED( hr ) )

{

hr = CoCreateInstance(CLSID_WMEncoder,

NULL,

CLSCTX_INPROC_SERVER,

IID_IWMEncoder,

(void**) &pEncoder);

}

// Retrieve the source group collection.

if ( SUCCEEDED( hr ) )

{

hr = pEncoder->get_SourceGroupCollection(&pSrcGrpColl);

}

// Add a source group to the collection.

if ( SUCCEEDED( hr ) )

{

hr = pSrcGrpColl->Add(CComBSTR("SG_1"), &pSrcGrp);

215

}

if ( SUCCEEDED( hr ) )

{

hr = pSrcGrp->AddSource(WMENC_VIDEO, &pSrc);

}

// Retrieve an IWMEncVideoSource2 pointer.

if ( SUCCEEDED( hr ) )

{

hr = pSrc->QueryInterface(IID_IWMEncVideoSource2, (void**)&pSrcVid);

}

// Add a video source to the source group.

if ( SUCCEEDED( hr ) )

{

hr = pSrcVid->SetInput(CComBSTR("ScreenCap://ScreenCapture1"));

}

// Retrieve a pointer to the property bag.

if ( SUCCEEDED( hr ) )

{

hr = pSrcVid->QueryInterface(IID_IPropertyBag, (void**)&pPropertyBag);

}

// Set full screen capture.

{

varValue = true;

216

if ( SUCCEEDED( hr ) )

{

hr = pPropertyBag->Write( WMSCRNCAP_ENTIRESCREEN, &varValue );

}

}

// Set the capture area.

{

// nLeft, nRight, nTop, and nBottom are the dimensions to capture

int nLeft, nRight, nTop, nBottom;

// Initialize the capture area. The size must be even.

varValue = false;

if ( SUCCEEDED( hr ) )

{

hr = pPropertyBag->Write( WMSCRNCAP_ENTIRESCREEN, &varValue );

}

varValue = nLeft;

if ( SUCCEEDED( hr ) )

{

hr = pPropertyBag->Write( WMSCRNCAP_WINDOWLEFT, &varValue );

}

varValue = nRight;

if ( SUCCEEDED( hr ) )

{

217

hr = pPropertyBag->Write( WMSCRNCAP_WINDOWRIGHT, &varValue );

}

varValue = nTop;

if ( SUCCEEDED( hr ) )

{

hr = pPropertyBag->Write( WMSCRNCAP_WINDOWTOP, &varValue );

}

varValue = nBottom;

if ( SUCCEEDED( hr ) )

{

hr = pPropertyBag->Write( WMSCRNCAP_WINDOWBOTTOM, &varValue );

}

varValue = true;

if ( SUCCEEDED( hr ) )

{

hr = pPropertyBag->Write( WMSCRNCAP_FLASHRECT, &varValue );

}

// Continue configuring the encoding session.

// Release pointers.

if ( pSrcGrpColl )

{

pSrcGrpColl->Release();

218

pSrcGrpColl = NULL;

}

if ( pSrcGrp )

{

pSrcGrp->Release();

pSrcGrp = NULL;

}

if ( pSrcVid )

{

pSrcVid->Release();

pSrcVid = NULL;

}

if ( pSrc )

{

pSrc->Release();

pSrc = NULL;

}

if ( pPropertyBag )

{

pPropertyBag->Release();

pPropertyBag = NULL;

}

if ( pEncoder )

{

pEncoder->Release();

pEncoder = NULL;

}

219

}

4.3.2.7.5 Thao tác với profile :

Một profile xác định codec nào được dùng để nén và quyết định số lượng dòng

xuất và tần suất bit của chúng. Mỗi profile nhắm đến các người dùng và mục đích khác

nhau. Chẳng hạn, một profile có thể với chất lượng dựa trên variable bit rate (VBR)

cho download tập tin, trong khi profile khác dùng constant bit rate (CBR) để tạo dòng.

Mỗi profile được dùng cho một số xác định và loại các dòng nguồn. Chỉ có một profile

có thể liên quan đến mỗi nhóm nguồn tại một thời điểm. và mọi nhóm nguồn phải dùng

cùng profile trong sessiion mã hóa.

Ta có thể dùng profile tùy biến (các tập tin .prx ) hay các profile hệ thống đi

kèm với Windows Media Encoder SDK. Dành cho các ứng dụng mã hóa mới, ta nên

tạo và dùng các profile tùy biến để đáp ứng nhu cầu của người dùng. Các profile hệ

thống không cập nhật cho các codec mới và không hỗ trợ tương thích ngược.

4.3.2.7.6 Thêm thông tin phụ:

o Thông tin hiển thị: thông tin sẽ xuất hiện trong trình chơi nhạc, bao gồm tên

tác giả và tên nghệ sĩ, tựa bài, mô tả, xếp loại, và bản quyền. Dùng

IWMEncDisplayInfo để thêm thông tin này.

o Thuộc tính của người dùng: thông tin này thêm vào form có từng cặp tên-giá

trị mà ta định nghĩa, cho phép ta thêm vào các thông tin thêm về session mã

hóa. Chẳng hạn, ta có thể thêm ngày và thể loại vào bằng cách dùng

IWMEncAttributes.

Ví dụ thêm thuộc tính tùy biến vào trong một tập tin truyền thông.

Ví dụ C++

#include

#include // Includes _bstr_T and _variant_T.

#include // Includes CComBSTR.

220

#include "wmencode.h"

// Declare variables.

HRESULT hr;

IWMEncoder* pEncoder;

IWMEncAttributes* pAttr;

CComBSTR m_bstrName;

CComVariant m_varValue;

CComVariant m_varIndex;

CComVariant m_varRemove;

long cnt;

// Initialize the COM library and retrieve a pointer

// to an IWMEncoder interface.

hr = CoInitialize( NULL );

if ( SUCCEEDED( hr ) )

{

hr = CoCreateInstance(CLSID_WMEncoder,

NULL,

CLSCTX_INPROC_SERVER,

IID_IWMEncoder,

(void**) &pEncoder);

}

// Retrieve a pointer to an IWMEncAttributes interface.

if ( SUCCEEDED( hr ) )

221

{

hr = pEncoder->get_Attributes( &pAttr );

}

// Add name-value pairs to the attributes collection.

_bstr_t bName[] =

{

_bstr_t("Date Created: "),

_bstr_t("Time Created: "),

_bstr_t("File Content: ")

}

_variant_t vVal[] =

{

_variant_t("02/15/2000"),

_variant_t("13:30:15"),

_variant_t("multimedia data"),

}

for( int i = 0; i < 3 && SUCCEEDED(hr); i++ )

{

hr = pAttr->Add(bName[i],vVal[i]);

}

// Retrieve the name-value pairs from the collection.

if ( SUCCEEDED( hr ) )

{

hr = pAttr->get_Count(&cnt);

222

}

for ( i = 0; i < cnt && SUCCEEDED( hr ); i++ )

{

hr = pAttr->Item(i, &m_bstrName, &m_varValue);

}

// Remove an attribute by name.

if ( SUCCEEDED( hr ) )

{

m_varRemove = "File Content: ";

hr = pAttr->Remove(m_varRemove);

}

// Remove an attribute by index.

if ( SUCCEEDED( hr ) )

{

m_varRemove = 0;

hr = pAttr->Remove(m_varRemove);

}

// Remove all attributes.

if ( SUCCEEDED( hr ) )

{

hr = pAttr->RemoveAll();

}

223

// Release pointers.

if ( pAttr )

{

pAttr->Release();

pAttr = NULL;

}

if ( pEncoder )

{

pEncoder->Release();

pEncoder = NULL;

}

4.3.2.7.7 Tiền xử lý âm thanh và hình ảnh:

Cho phép thực hiện việc lọc khung, xén hình, và tạo họa tiết cho dữ liệu đầu ra.

Ta không đi sâu vào các chi tiết phức tạp của phần này.

4.3.2.7.8 Xác định dữ liệu đầu ra:

4.3.2.7.8.1 Lưu nội dung mã hóa xuống tập tin:

Ta có thể lưu nội dung của một tập tin Windows Media, hoặc song song với ứng

dụng broadcast hoặc chỉ riêng lưu tập tin. Ta có thể hạn chế kích thước tập tin xuất khi

lưu, hoặc bằng khỏang xử lý dài nhất hay kích thước tập tin lớn nhất.

Ta cũng có thể xác định nhóm nguồn nào cần lưu trữ. Chẳng hạn, nếu ta mã hóa

một màn hình chào mừng tĩnh, một buổi trình diễn sống và một màn hình kết thúc tĩnh,

ta có thể chỉ muốn lưu trữ buổi trình diễn sống. Mặc định, các nhóm nguồn tự động lưu

trữ, vì vậy đặt thuộc tính AutoArchive trong IWMEncSourceGroup.AutoArchive để

Dừng hẳn hoặc Ngưng các nhóm nguồn ta không muốn lưu.

224

Để điều khiển bằng tay việc khởi động, dừng, ngưng quá trình xử lý lưu, đặt

phương thức Archive dùng IWMEncoder hay WMEncoder. Mặc định, việc lưu trữ

bắt đầu ngay khi mã hóa bắt đầu. Nếu muốn điều khiển bằng tay, đặt thuộc tính

EnableAutoArchive bằng false.

Ví dụ mô tả việc lưu nội dung mã hóa xuống tập tin bằng IWMEncFile2.

Ví dụ C++

// Include libraries.

#include

#include "wmencode.h"

// Declare variables.

HRESULT hr;

IWMEncoder* pEncoder;

IWMEncFile* pFile;

// Initialize the COM library and retrieve a pointer

// to an IWMEncoder interface.

if ( SUCCEEDED( hr ) )

{

hr = CoCreateInstance( CLSID_WMEncoder,

NULL,

CLSCTX_INPROC_SERVER,

IID_IWMEncoder,

(void**) &pEncoder);

}

// Specify a file in which to save encoded content.

225

if ( SUCCEEDED( hr ) )

{

hr = pEncoder->get_File(&pFile);

}

if ( SUCCEEDED( hr ) )

{

hr = pFile->put_LocalFileName(CComBSTR("C:\\filename.wmv"));

}

// Release pointers.

if ( pFile )

{

pFile->Release();

pFile = NULL;

}

if ( pEncoder )

{

pEncoder->Release();

pEncoder = NULL;

}

4.3.2.7.8.2 Đẩy một dòng lên Windows Media Server

Ta có thể broadcast một dòng bằng cách đẩy nó lên một Windows Media

Server, rất hữu ích khi ta muốn khởi tạo kết nối từ một ứng dụng mã hóa.

Khi đẩy một dòng lên một Windows Media Server, ta cần biết :

o Tên của Windows Media Server. Tên này có thể là alias, một fully qualified

domain name, hay địa chỉ IP.

226

o Tên của điểm xuất bản mới hay có sẵn.

o Tùy chọn, tên điểm xuất bản cho cấu hình thiết lập.

Đây là phần liên quan đến phiên bản Windows hỗ trợ Windows Media Server,

ta không đi sâu vào phần này.

4.3.2.7.8.3

Broadcast một dòng từ ứng dụng Windows Media

Encoder:

Broadcast một dòng bằng cách cho phép những máy khách (Windows Media

Server, Web Server, hay player) để kết nối trực tiếp với máy chạy ứng dụng Windows

Media Encoder để kéo dòng về.

Máy khách kết nối với dòng bằng cách dùng http://Địa chỉ:cổng cho kết nối

Internet hay http://tên_máy_mã_hóa:cổng cho kết nối LAN. Ta có thể ngăn cấm truy

cập theo mặt nạ IP.

Để broadcast một dòng từ máy chủ, dùng IWMEncBroadcast để xác định nghi

thức và số hiệu cổng để có thể broadcast.

Ví dụ C++

// Include libraries.

#include

#include "wmencode.h"

// Declare variables.

HRESULT hr;

IWMEncoder* pEncoder;

IWMEncBroadcast* pBrdcst;

// Initialize the COM library and retrieve a pointer

// to an IWMEncoder interface.

227

if ( SUCCEEDED( hr ) )

{

hr = CoCreateInstance( CLSID_WMEncoder,

NULL,

CLSCTX_INPROC_SERVER,

IID_IWMEncoder,

(void**) &pEncoder);

}

// Specify a broadcast protocol and port number.

if ( SUCCEEDED( hr ) )

{

hr = pEncoder->get_Broadcast(&pBrdcst);

}

if ( SUCCEEDED( hr ) )

{

hr = pBrdcst->put_PortNumber(WMENC_PROTOCOL_HTTP, 8080);

}

// Release pointers.

if ( pBrdcst )

{

pBrdcst->Release();

pBrdcst = NULL;

}

if ( pEncoder )

{

228

pEncoder->Release();

pEncoder = NULL;

}

4.3.2.8 Quản trị từ xa ứng dụng mã hóa:

Quản trị viên có thể điều khiển nhiều thể hiện các ứng dụng Windows Media

Encoder trên máy ở xa hoặc bằng LAN hay Internet. Bằng cách dùng các giao diện

IWMEncAgentLocator, IWMEncoderAgent và IWMEncoderNamesCollection, ta

có thể viết các ứng dụng cho phép :

o Tạo các đối tượng WMEncoderApp trên các máy ở xa.

o Liệt kê các đối tượng WMEncoder trên máy cho trước.

o Kết nối và điều khiển một đối tượng WMEncoder.

o Quan sát trạng thái của quá trình xử lý mã hóa.

Windows Media Encoder phải cài sẵn trên máy ở xa, và ta phải dùng tiện ích

cấu hình DCOM để thiết lập việc khởi phát, truy cập, và cho phép cấu hình cho cả

Windows Media Encoder và Windows Media Encoder Agent. Để tạo các đối tượng

WMEncoderApp, đối tượng WMEncoderAgent phải chạy trên máy ở xa. Ta có thể

khởi động đối tượng WMEncoderAgent bằng tay hay tự động.

4.3.2.9 Phụ chú:

Các phần ta không đi sâu, để biết rõ hơn có thể xem ở tài liệu Windows Media

Encoder SDK Documentation đi kèm với bộ SDK.

Chương 5 Tổng kết

5.1 Kết luận:

5.1.1 Kết quả đạt được:

Sau khi thực hiện đề tài, chúng em thu được một số kết quả sau:

229

• Tìm hiểu được công nghệ truyền hình ảnh âm thanh trên mạng LAN và Internet

H323. Đây là một công nghệ mã nguồn mở đa nền, rất hữu ích trong việc viết

các ứng dụng chạy trên nhiều hệ điều hành khác nhau.

• Tìm hiểu được bộ phát triển phần mềm Microsoft Windows Media Encoder.

Với khả năng tích hợp chặt chẽ với hệ điều hành Windows, Windows Media

Encoder SDK rất thích hợp cho tìm hiểu các khái niệm về mã hóa, giải mã các

dòng âm thanh, hình ảnh trên hệ điều ảnh Windows.

• Tìm hiểu được nghi thức RFB, một nghi thức đơn giản nhằm giao tiếp điều

khiển máy tính từ xa. Chúng em cũng thu lượm được các kiến thức về vùng đệm

khung dành cho màn hình, khả năng xây dựng tối ưu hóa cách viết mã từ mã

nguồn mở của nghi thức.

• Tìm hiểu được các kỹ thuật kiểm sóat hệ thống một cách triệt để, khả năng lập

trình tương tác cấp thấp với bộ nhớ, thiết bị, tùy biến giao diện trên cũng như

các cơ chế quản lý hệ thống của hệ điều hành Windows.

• Xây dựng thành công một chương trình điều khiển máy tính từ xa, đồng thời

qua đó, nắm được khả năng tích hợp và sử dụng được các đồ án mã nguồn mở

do cộng đồng công nghệ thông tin thế giới cung cấp không vụ lợi.

5.1.2 Hạn chế:

Mặc dù chúng em đã cố gắng hết sức nhưng ứng dụng vẫn còn một số hạn

chế nhất định:

• Ứng dụng vẫn chưa kiểm tra được tính ổn định cao trên nhiều máy.

• Chưa tối ưu hóa trong việc truyền gởi dữ liệu giữa chương trình điều khiển và

chương trình bị điều khiển.

• Ứng dụng có thể chiếm dụng bộ nhớ khi thực hiện việc quan sát màn hình máy

khách.

230

5.2 Hướng phát triển

Với những kết quả đạt được và những hạn chế nêu trên, đề tài có thể mở rộng

theo các hướng sau:

• Mở rộng khả năng kiểm soát : không những hệ thống máy khách mà cả nội dung

người dùng lướt web bằng các cách như lọc liên kết, nội dung trang web.

• Mở rộng thêm các loại hình phục vụ : như nhắn tin điện thoại di động…

• Cải thiện độ ổn định và vấn đề bộ nhớ cho chương trình.

231

TÀI LIỆU THAM KHẢO

Tài liệu viết :

Tài liệu trong nước

[1] Nguyễn Tri Tuấn, Cơ sở lý thuyết về lập trình sự kiện và hook (chặn các thông

điệp), môn học Lập trình C trên Windows, 24/2/2004.

[2] Nguyễn Tri Tuấn, Thư viện liên kết động, môn học Lập trình C trên Windows,

24/2/2004.

Tài liệu nước ngoài

[3] Robert Kuster, Three Ways to Inject Your Code into Another Process,

www.codeproject.com, 25/7/2003 cập nhật 21/8/2003.

[4] António Feijão, Lock Windows Desktop, www.codeproject.com, 14/6/2004 cập

nhật 9/12/2004.

[5] Fad B, Using GINA.DLL to Spy on Windows User Name & Password And to

Disable SAS (Ctrl+Alt+Del), www.codeproject.com, 22/8/2003.

[6] =[ Abin ]=, An All-Purpose Keyboard Hooker, www.codeproject.com,

13/5/2004 cập nhật 31/5/2004.

[7] Microsoft Development Network (MSDN), tài liệu các loại, Microsoft Visual

Studion 6.0, 10/2003.

[8]

Joseph M. Newcomer, Hook and DLLs, www.codeproject.com, 1/4/2001.

[9] Derek Lakin, CTabCtrlSSL - An easy to use, flexible extended tab control,

www.codeproject.com, 21/9/2001.

[10] dang!, Ownerdraw Tab Controls - Borders and All, www.codeproject.com,

31/1/2002 cập nhật 1/7/2002.

[11] Barry, Barry's Screen Capture, www.codeguru.com, 4/2/2003.

232

[12] P.GopalaKrishna, Various methods for capturing the screen, 24/8/2003.

[13] Carlos Antollini, A set of ADO Classes - version 2.04, www.codeproject.com,

25/4/2001 cập nhật 3/8/2002.

[14] Tristan Richardson, The RFB Protocol version 3.8, RealVNC Ltd, 8/3/2005.

[15] Davide Calabro, CButtonST v3.9 (MFC Flat buttons), www.codeproject.com,

25/11/1999 cập nhật 29/3/2003.

[16] Nischant S, Tile, center and stretch a bitmap as your MFC dialog background,

www.codeproject.com, 7/6/2002.

[17] PJ Naughter, Splasher v1.32

- A Splash Screen

Implementation,

www.codeproject.com, 4/3/2000.

[18] Mark Jackson, Sort List Control, www.codeproject.com, 7/9/2001.

[19] Chris Maunder, Adding Icons to the System Tray, www.codeproject.com,

30/11/1999 cập nhật 3/8/2003.

Websites :

[20] Codeproject, http://www.codeproject.com.

[21] RealVNC Ltd, http://www.realvnc.com.

[22] H323, http://www.openh323.org.

[23] Vox Gratia, http://www.voxgratia.org.

[24] Microsoft Corporation, http://www.microsoft.com.

[25] Codeguru, http://www.codeguru.com.

[26] Source Forge, http://www.sourceforge.net.

233