1. Trang chủ
  2. » Giáo Dục - Đào Tạo

BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN

81 483 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 81
Dung lượng 3,06 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Tại cácphòng máy đó các giảng viên có thể dễ dàng truyền đạt kiến thức một cách sinh động,trực quan cho các học viên bằng cách sử dụng chức năng chia sẻ màn hình của phầnmềm quản lý phòn

Trang 1

TRƯỜNG ĐẠI HỌC CÔNG NGHIỆP HÀ NỘI

KHOA CÔNG NGHỆ THÔNG TIN

Giảng viên hướng dẫn: TH.S NGUYỄN TIẾN LỢI

Trang 2

Hà Nội, 05/2012

PHIẾU GIAO ĐỀ TÀI

Trang 3

NHẬN XÉT CỦA GIÁO VIÊN HƯỚNG DẪN

Hà Nội, ngày tháng năm 2012 Giảng viên

Trang 4

Th.S Nguyễn Tiến Lợi

LỜI NÓI ĐẦU

Công nghệ thông tin là ngành công nghiệp mũi nhọn của thế giới nói chung vàcủa Việt Nam nói riêng, nó đã phát triển mạnh mẽ không ngừng trong những năm gầnđây Số lượng các trường học có đào tạo nghành CNTT ngày một tăng cao, cùng với

đó là các trung tâm tin học mở ra ngày một nhiều Và lẽ tự nhiên khi các trường, cáctrung tâm muốn có các phòng máy chất lượng thì họ cũng sẽ có nhu cầu sử dụng các

hệ thống quản lý phòng máy đa năng, tiện dụng và thân thiện người sử dụng Tại cácphòng máy đó các giảng viên có thể dễ dàng truyền đạt kiến thức một cách sinh động,trực quan cho các học viên bằng cách sử dụng chức năng chia sẻ màn hình của phầnmềm quản lý phòng máy, hoặc giảng viên có thể chỉ dẫn cho học viên trực tiếp trênmàn hình của học viên chỉ bằng thao tác đơn giản giống như trực tiếp giảng viên ngồitại máy của học viên …

Do đó việc xây dựng một phần mềm lớp học ảo trong mạng Lan là một việc rấtcần thiết, nhằm hỗ trợ các giảng viên cũng như hỗ trợ các học viên có thể tiếp cậnđược với cách học tập trực quan dễ hiểu Nhận thức được tầm quan trọng cũng nhưcấp thiết phải có một hệ thống quản lý các máy tính trong phòng học mạng Lan Nhómchúng em đã đăng ký đề tài “Xây dựng phần mềm lớp học ảo trong mạng Lan” Với hivọng phần mềm sẽ giải quyết được phần nào trong quá trình dạy và học trong phòngmáy sử dụng mạng Lan Và tiến xa hơn đó là một phần mềm đào tạo thông qua mạngInternet, ở đó cả học viên và giảng viên có thể truy cập từ bất kỳ máy tính nào đượccài đặt phần mềm việc học tập và giảng dạy sẽ càng trở lên dễ dàng hơn

Để hoàn thành báo cáo thực tập tốt nghiệp này, chúng em đã được sự giúp đỡ

tận tình của giảng viên hướng dẫn - Th.S Nguyễn Tiến Lợi - Giảng viên khoa CNTT

trường Đại Học Công Nghiệp Hà Nội, Thầy đã tận tình hướng dẫn, góp ý chỉnh sửa rấtchi tiết cho bài báo cáo của chúng em Chúng em xin chân thành gửi lời cảm ơn sâusắc tới Thầy Xin chúc Thầy và gia đình luôn mạnh khỏe và thạnh phúc

Trang 5

TÓM TẮT NỘI DUNG BÁO CÁO THỰC TẬP TỐT NGHIỆP

1 Những nội dung sẽ được trình bày trong bài báo cáo.

Đề xuất xây dựng một phần mềm lớp học ảo trong mạng Lan có những chứcnăng chính sau đây

 Chia sẻ màn hình giảng dạy

 Chia sẻ tài liệu học tập

 Chat Message

 Điều khiển máy tính từ xa (Remote Desktop)

 Hỗ trợ giảng viên một số chức năng và tiện ích khác

Đưa ra các kiến thức, kỹ thuật cơ bản và quan trọng về lập trình mạng vớiSocket và Net Remoting

Nghiên cứu các lĩnh vực lập trình nâng cao như các hàm API, lập trình xử lýảnh có ứng dụng cụ thể trong bài toán

Báo cáo về quá trình để xây dựng các module chính của phần mềm, và sau đótiến hành xây dựng một phần mềm hoàn thiện

Đưa ra một phần mềm hoàn thiện và đánh giá về các kết quả thực nghiệm

2 Cấu trúc của báo cáo.

 Chương 1 Tổng quan về đề tài

 Chương 2 Lý thuyết cơ sở

 Chương 3 Ứng dụng phần mềm quản lý lớp học ảo

 Chương 4 Cài đặt và thử nghiệm

 Chương 5 Kết luận

 Tài liệu tham khảo và kiến nghị

Trang 6

DANH SÁCH HÌNH ẢNH

Hình 2 1: Chức năng của Socket 16

Hình 2 2 Sơ đồ giao tiếp các máy tính khác nhau 17

Hình 2 3: Các chế độ giao tiếp các tầng mạng khác nhau 18

Hình 2 4 Minh họa quá trình khởi tạo TCP Socket Server 19

Hình 2 5 Mô tả quá trình khởi tạo TCP Socket Client kết nối tới Server 19

Hình 2 6 Mô tả quá trình truyền nhận thông tin giữa Server và Client 20

Hình 2 7 Mô tả kết thúc phiên làm việc giữa Client và Server 20

Hình 2 8 Mô tả quá trình khởi tạo UDP Socket Server 21

Hình 2 9 Mô tả quá trình khởi tạo UDP Socket Client 21

Hình 2 10 Mô tả quá trình truyền nhận dữ liệu bằng UDP 22

Hình 2 11 Mô hình trao đổi thông tin của Net Remoting 29

Hình 2 12 Lập trình sự kiện trong Windows 33

Hình 2 13 Gửi và nhận sự kiện trong Windows 34

Hình 2 14 Kết quả chương trình không sử dụng đồng bộ hóa 41

Hình 2 15 Kết quả chương trình sử dụng đồng bộ hóa 42

Hình 2 16 Biểu diễn ảnh trong hệ màu RGB 46

Hình 2 17 Mô tả thuật toán cắt ảnh 46

Hình 2 18 Mô tả ma trận điểm ảnh 47

Hình 2 19 Minh họa thuật toán so sánh ảnh 47

Hình 3 1 Mô hình phân cấp chức năng

56

Hình 3 2 Hình minh họa chức năng chia sẻ màn hình 57

Hình 3 3 Các nội dung giảng dạy có trên màn hình các máy học viên 57

Hình 3 4 Minh họa chia sẻ màn hình cho toàn bộ học viên 58

Hình 3 5 Minh họa các tài liệu được chia sẻ 58

Hình 3 6 Minh họa chức năng chia sẻ màn hình 59

Hình 3 7 Mô hình luồng dữ liệu 60

Trang 7

DANH MỤC BẢNG BIỂU

Bảng 1 1 Cấu hình tối thiểu của phòng máy 13

Bảng 1 2 Cấu hình được khuyến cáo trong phòng máy 13

Bảng 2 1 Một số phương thức của lớp NetworkStream 23

Bảng 2 2 Một số phương thức lớp StreamRead 24

Bảng 2 3 Một số phương thức lớp StreamWriter 24

Bảng 2 4 Các thành viên của lớp TCPClient 25

Bảng 2 5 Các phương thành viên của lớp TCPListener 26

Bảng 2 6 các thành viên của lớp UDPClient 27

Bảng 2 7 Các phương thức của lập trình Socket bất đồng bộ 28

Bảng 2 8 Một số lớp thuộc tính của thư viện System.Thread 36

Bảng 2 9 Các thành phần static của lớp Thread 36

Bảng 2 10 Các thành viên cấp đối tượng của lớp Thread 37

Bảng 2 11 Các thành phần chính của Registry 53

Trang 8

DANH MỤC CÁC THUẬT NGỮ VIẾT TẮT Danh sách từ viết tắt Nghĩa của từ

LanVC Lan Virual Class (Phần mềm lớp học ảo)

TCP Transmission Control Protocol

RGB Không gian màu gồm ba màu Red - Blue - Green

MỤC LỤC PHIẾU GIAO ĐỀ TÀI 2 NHẬN XÉT CỦA GIÁO VIÊN HƯỚNG DẪN 3

Trang 9

LỜI NÓI ĐẦU 4

TÓM TẮT NỘI DUNG BÁO CÁO THỰC TẬP TỐT NGHIỆP 5

DANH SÁCH HÌNH ẢNH 6

DANH MỤC BẢNG BIỂU 7

DANH MỤC CÁC THUẬT NGỮ VIẾT TẮT 8

MỤC LỤC 9

CHƯƠNG 1 TỔNG QUAN VỀ ĐỀ TÀI 12

1.1 Lý do chọn đề tài 12

1.2 Tình hình nghiên cứu trên thực tế 12

1.3 Vấn đề đặt ra của đề tài 13

1.3.1 Một số vấn đề về cấu hình của hệ thống 13

1.3.2 Đề xuất các module 13

1.4 Mục tiêu của đề tài 14

1.5 Đối tượng và phương pháp nghiên cứu 14

1.5.1 Đối tượng nghiên cứu 14

1.5.2 Phương pháp nghiên cứu 14

1.6 Dự kiến các kết quả nghiên cứu 15

1.7 Kết luận 15

CHƯƠNG 2 LÝ THUYẾT CƠ SỞ 16

2.1 Lập trình Socket C# 16

2.1.1 Socket là gì? 16

2.1.2 Chức năng của Socket 16

2.1.3 Phân loại Socket 16

2.1.4 Thành phần của một Socket 17

2.1.4.1 Số hiệu cổng (port number) 17

2.1.4.2 Địa chỉ IP 17

2.1.5 Các chế độ giao tiếp 18

2.1.6 Xây dựng ứng dụng Client-Server với Socket: 18

2.1.6.1 Mô hình Client-Server sử dụng Socket ở chế độ có kết nối (TCP) 19

2.1.6.2 Mô hình Client-Server sử dụng Socket ở chế độ không kết nối (UDP) 20

2.1.7 Sử dụng C# Stream với TCP 22

2.1.7.1 Lớp NetworkStream 22

2.1.7.2 Lớp StreamReader và StreamWriter 23

2.1.8 Sử dụng các lớp Helper Socket 24

2.1.8.1.TCPClient 24

2.1.8.2 TCPListener 25

2.1.8.3 UDPClient 26

2.1.9 Lập trình Socket bất đồng bộ 27

2.1.9.1 Thành lập kết nối 28

2.1.9.2 Trao đổi dữ liệu 28

2.2 Lập trình Net Remoting 29

2.2.1 Các khái niệm 29

2.2.2 Remote Objects trong NET Remoting 29

2.2.3.Domain 30

2.2.4.Channel 30

2.2.5 Object Activation 31

2.2.6 Client Activated Objects 31

2.2.7 Tạo một Remotable Object 32

2.3 Lập trình sự kiện trong Windows 33

2.3.1 Sử dụng Event và Delegate 33

Trang 10

2.4 Lập trình đa luồng 34

2.4.1 Khái niệm đa luồng (Thread) 34

2.4.2 Tham khảo thư viện System.Thread 35

2.4.2 Lớp Thread 36

2.4.3 Thao tác với luồng 37

2.4.4 Đồng bộ hóa (Synchronization) trong lập trình đa luồng 39

2.4.4.1 Đồng bộ hóa 39

2.4.4.2 Deadlock 42

2.4.4.3 Race condition 43

2.5 Lập trình xử lý ảnh trong C# 45

2.5.1 Một số khái niệm xử lý ảnh 45

2.5.1.1 Khái niệm ảnh 45

2.5.2 Kỹ thuật xử lý ảnh cơ bản 46

2.5.2.1 Thuật toán cắt ảnh 46

2.5.2.2 Thuật toán so sánh hai ảnh bitmap 47

2.6 Một số kỹ thuật khác 48

2.5.1 Các hàm API 48

2.5.1.1 Khái niệm API 48

2.5.1.2 Các thành phần của Windows API 48

2.5.1.3 Cách dùng các hàm API 48

2.5.1.4 Sử dụng các hàm API 49

2.5.2 XML 50

2.5.2.1 Khái niệm về XML 50

2.5.2.2 Các quy tắc viết thẻ XML 51

2.5.3 Registry trong C# 51

2.5.3.1 Khái niệm Registry 51

2.5.3.2 Các lớp Net Registry 51

2.7 Kết luận chương 53

CHƯƠNG 3 ỨNG DỤNG PHẦN MỀM QUẢN LÝ LỚP HỌC ẢO 54

3.1 Phân tích thiết kế hệ thống 54

3.1.1.Khảo sát hiện trạng và lập dự án 54

3.1.1.2 Đề xuất ý tưởng xây dựng hệ thống mới 54

3.1.1.3 Mô tả hoạt động của hệ thống 54

3.1.2 Phân tích các chức năng của hệ thống 55

3.1.2.1 Mô hình phân cấp chức năng 55

3.1.2.2 Giải thích rõ từng chức năng của hệ thống 56

3.1.2.3 Mô hình luồng dữ liệu 59

3.2 Xây dựng các lớp xử lý chính 60

3.2.1 Các lớp bên phía Server 60

3.2.1.1 Lớp ServerReceiver 60

3.2.1.2 Lớp ServerSender 62

3.2.1.3 Lớp ServerTCP 65

3.2.1.4 Lớp BuffData 70

3.2.2 Các lớp bên phía Client 71

3.2.2.1 Lớp ClientReceiver 72

3.2.2.2 Lớp ClientSender 74

3.2.2.3 Lớp ClientTCP 76

3.3 Thiết kế giao diện 79

CHƯƠNG 5 KẾT LUẬN 80

5.1 Những kết quả đạt được 80

Trang 11

5.2 Hướng phát triển 80 TÀI LIỆU THAM KHẢO 81

CHƯƠNG 1 TỔNG QUAN VỀ ĐỀ TÀI 1.1 Lý do chọn đề tài.

Trang 12

Hiện nay, với sự phát triển vượt bậc của khoa học công nghệ trong đời sống xãhội Việc ứng dụng công nghệ mạng Lan vào trong việc giảng dạy tại các trường ĐạiHọc, và Cao Đẳng ngày càng phát triển Nhưng việc quản lý phòng học trong mạngLan còn nhiều bất cập

 Tốn kém đầu tư tiền của vào hệ thống máy chiếu, bảng hiện tại

 Khó khăn trong khâu chia sẻ tài liệu học tập

 Giáo viên khó khăn trong quá trình giảng dạy, và giải đáp thắc mắc họcviên

 Không có nhiều sự tương tác giữa giảng viên và học sinh

Vì vậy xuất phát từ vấn đề đó nhóm chúng em quyết định lựa chọn đề tài “Xây

dựng phần mềm lớp học ảo trong mạng Lan” Với mong muốn đem lại một phần

mềm giúp tận dụng sức mạnh của CNTT đem lại hiệu quả cho việc giảng dạy trongcác phòng học hiện tại

1.2 Tình hình nghiên cứu trên thực tế.

Hiện nay trên thị trường cũng đã có các sản phẩm phần mềm có tính năngtương tự hoặc một số phần mềm có tính năng như một module nhỏ của phần mềm lớphọc ảo

 Farstone Virtual Class

 Ưu điểm : Là một phần mềm của hãng FarStone đưa ra với mụcđích quản lý lớp học ảo gần như rất hoàn hảo, nó có thể cho phépgiảng viên và học sinh tương tác với nhau vô cùng đơn giản vàtiện lợi

 Nhược điểm : giá cả của nó thì không hề dẻ chút nào với 299$

Và nó còn thiếu một tính năng đó là chức năng quay phim mànhình và Void chat trong lớp học

 Remote Desktop Connection

 Ưu điểm : là một phần mềm của hãng Micosoft được chạy trênWindows 7 và Windows Vista và nó là một phần mềm miễn phí,

và sử dụng được một cách linh hoạt

 Nhược điểm : còn có nhiều thiếu sót đó là chỉ có chức năngremote desktop từ xa mà không hề có chức năng như giảng dạy,

Do đó phần mềm này chỉ giúp ích được không nhiều trong việcquản lý lớp học ảo Và thêm nữa là chúng ta cần phải nhớ tên củamáy Client và Password đây là việc cực kỳ bất tiện

 FreeVC

Trang 13

 Ưu điểm : là một phần mềm của người việt được viết bởi tác giảBùi Duy Hùng, phần mềm này đã nhận được giải thưởng phầnmềm sáng tạo của trường Đại học Công Nghiệp Hà Nội Phầnmềm này được đánh giá là tiện ích như phần mềm FarstoneVirtual Class nhưng nó là một phần mềm miễn phí và hiệu năng

và tính năng đơn giản dễ sử dụng

 Nhược điểm : tuy vậy phần mềm này còn nhiều thiếu sót nhưquản lý Usb, Turn Off Computer, và một vài chức năng khác

 Microsoft NetMeeting :

 Ưu điểm : cũng là một phần mềm của hãng Microsoft có hỗ trợtrên Windows XP nó có thể cho phép người sử dụng dùng để tổchức hội thảo, nhìn thấy người nói chuyện với mình, hoặc có thểchia sẻ tài liệu một cách dễ dàng

 Nhược điểm : tuy vậy phần mềm còn có khá nhiều vấn đề như nókhông thể xem các máy Client khi cần thiết, mà nó chỉ xem đượcdanh sách các máy Client Và một vài khuyết điểm khác như khóaUsb, quản lý các máy Client khi cần thiết

1.3 Vấn đề đặt ra của đề tài.

Dựa vào tình hình nghiên cứu các phần mềm trên thực tế chúng ta sẽ tiến hànhxây dựng lên một phần mềm hoàn hảo hơn, nhằm loại bỏ đi những khuyết điểm củacác phần mềm thực tế, và tận dụng hết các điểm mạnh của phần mềm thực tế

Ram 256 MB CPU Ce 1.8 GHz LAN network

Software

Window XP SQL Server 2005 Net framework 3.5

Trang 14

LAN network LAN network

Software

Window Server 2003

SQL Server 2005 Net framework 3.5

Windows XP

.Net framework 3.5

Bảng 1 2 Cấu hình được khuyến cáo trong phòng máy.

1.3.2 Đề xuất các module

Như trong phần 1.1 và 1.2 chúng ta đã được biết mức độ cấp bách và cần thiết

phải thực hiện “Xây dựng phần mềm lớp học ảo trong mạng Lan” Do đó phần mềmcủa chúng em được đề xuất các module chính sau đây cần thiết phải thực hiện

Module chia sẻ (gồm chia sẻ tài liệu, chia sẻ màn hình, thực hiện việc trao đổithông tin bằng chat message)

Module tiện ích (gồm có Turn off computer, Disable/Enable Usb disk, Remotedesktop, và chức năng VoIP)

Trong đó có hai module chính quan trọng và cần thiết nhất cần giải quyết đó vàRemote desktop và chia sẻ màn hình Hai module này về giải thuật và cách xây dựng

là tương đối giống nhau

1.4 Mục tiêu của đề tài.

 Đưa ra những giải pháp cụ thể của phần mềm để giải quyết các bất cập đãnêu

 Đề xuất xây dựng một phần mềm với mục đích giúp việc học tập và giảngdạy tại lớp học trong mạng Lan trở lên dễ dàng và trực quan hơn

 Xây dựng một mô hình cụ thể cho vấn đề đang nghiên cứu Và đưa mô hình

đó vào ứng dụng thực tế

1.5 Đối tượng và phương pháp nghiên cứu.

1.5.1 Đối tượng nghiên cứu

 Tìm hiểu các kỹ thuật cơ bản của lập trình mạng với Socket, và .NetRemoting

 Nghiên cứu về lập trình Thread, lập trình sự kiện Delegate

 Tìm hiểu các kỹ thuật trong lập trình sử dụng các hàm API ứng dụng vàobài toán lập trình phần mềm lớp học ảo

 Ngoài ra còn nghiên cứu lập trình xử lý ảnh trong C# trong vấn đề giảiquyết bài toán chia sẻ màn hình và điều khiển máy tính từ xa

1.5.2 Phương pháp nghiên cứu

Trang 15

 Tìm hiểu các kiến thức về lập trình mạng với Socket và Net Remotingthông qua các giáo trình, các bài viết về lập trình mạng trên các diễn đàn -song song với việc tham khảo từ tài liệu của giáo viên hướng dẫn.

 Tham khảo các kiến thức về lập trình xử lý ảnh, lập trình các hàm API vàThread trong sách vở cũng như trên các website

 Tìm kiếm các mã nguồn mở về các mảng cần nghiên cứu trên các websitenhư codeproject.com, codeplex.com, sourceforge.net, github.com Nhằmmục đích tìm hiểu về quá trình cài đặt thuật toán xử lý cơ bản và nâng caotrên ngôn ngữ lập trình C/C++ và C#

 Từng bước nghiên cứu, đánh giá và đề xuất các kỹ thuật sử dụng trong phầnmềm

 Thực nghiệm dựa trên xây dựng ứng dụng và đánh giá các kết quả đã thựchiên được và những kết quả chưa thực hiện được Từ đó đưa ra các giảipháp và các triển vọng của đề tài

1.6 Dự kiến các kết quả nghiên cứu.

 Hoàn thiện quá trình nghiên cứu, đưa ra một số kỹ thuật cơ bản trong quátrình lập trình mạng

 Xây dựng một báo cáo cụ thể và chi tiết về các kỹ thuật lập trình Thread,API và xử lý ảnh được ứng dụng trong bài toán

 Cài đặt và xây dựng một phần mềm lớp học ảo thực tế Và sau đó đánh giácác kết quả thực nghiệm

Kết luận chương.

Nội dung chương này chúng em sẽ trình bầy lý do để chọn ra đề tài, các nộidung và các mục cần thiết để nghiên cứu, đưa ra các module cần thiết phải xây dựngtrong chương trình Và đưa ra dự kiến thực hiện đề tài gồm : báo cáo và chương trìnhdemo các kết quả đã đạt được

Trang 16

CHƯƠNG 2 LÝ THUYẾT CƠ SỞ 2.1 Lập trình Socket C#.

2.1.1 Socket là gì?

Socket là một phương pháp để thiết lập kết nối truyền thông giữa một chươngtrình yêu cầu dịch vụ ( client) và một chương trình cung cấp dịch vụ (server) trênmạng LAN, WAN hay Internet và đôi lúc là giữa những tiến trình ngay trong một máytính Mỗi socket có thể được xem như một điểm cuối (EndPoint) trong một kết nối

Một socket trên máy yêu cầu dịch vụ có địa chỉ mạng được cấp sẵn để “gọi”một socket trên máy cung cấp dịch vụ Một khi socket đã được thiết lập phù hợp, haimáy tính có thể trao đổi dịch vụ và dữ liệu

Socket được giới thiệu lần đầu tiên trong ấn bản UNIX - BSD 4.2 dưới dạngcác hàm hệ thống theo cú pháp ngôn ngữ C (socket(), bind(), connect(), send(),receive(), read(), write(), close() , ) Ngày nay, Socket được hỗ trợ trong hầu hết các

hệ điều hành như MS Windows (WinSock), Linux và được sử dụng trong nhiều ngônngữ lập trình khác nhau: như C, C++, C#, Java, Visual Basic, Visual C++

Dữ liệu gởi và nhận bằng Socket bắt buộc phải là mảng các byte

2.1.2 Chức năng của Socket

Socket cho phép thiết lập các kênh giao tiếp mà hai đầu kênh được xác định bởihai cổng (port) Thông qua các cổng này một tiến trình có thể nhận và gởi dữ liệu vớicác tiến trình khác

Hình 2 1: Chức năng của Socket.

2.1.3 Phân loại Socket

Có các loại Socket chính là:

 Socket kiểu AF_UNIX chỉ cho phép giao tiếp giữa các tiến trình trong cùngmột máy tính

Trang 17

 Socket kiểu AF_INTET cho phép giao tiếp giữa các tiến trình trên nhưngmáy tính khác nhau trên mạng

Phân loại theo kiểu kết nối:

 Socket hướng kết nối (TCP Socket)

 Socket không hướng kết nối (UDP Socket)

2.1.4 Thành phần của một Socket

2.1.4.1 Số hiệu cổng (port number)

Để có thể thực hiện các cuộc giao tiếp, một trong hai tiến trình phải cho biết sốhiệu cổng của socket mà mình sử dụng Mỗi cổng giao tiếp thể hiện một địa chỉ xácđịnh trong một hệ thống Khi tiến trình được gán một số hiệu cổng (Server), nó có thểnhận dư liệu gởi đến cổng này từ tiến trình khác (Client) Tiến trình còn lại cũng 8 yêucầu tạo ra một socket

2.1.4.2 Địa chỉ IP

Ngoài số hiệu cổng, hai bên giao tiếp còn phải biết địa chỉ IP của nhau Trongkhi số hiệu cổng dùng để phân biệt các quá trình khác nhau trên cùng một máy tính thì

IP dùng để phân biệt các máy tính khác nhau trên cùng một mạng TCP/IP

Hình 2 2 Sơ đồ giao tiếp các máy tính khác nhau.

Trong hình trên, địa chỉ của tiến trình B1 được xác định bằng 2 thông tin: (Host

Trang 18

2.1.5 Các chế độ giao tiếp

Xét kiến trúc của hệ thống mạng TCP/IP:

Hình 2 3: Các chế độ giao tiếp các tầng mạng khác nhau.

Tầng vận chuyển (Transport Layer) giúp chuyển tiếp các thông điệp giữa cácchương trình với nhau Nó có thể hoạt động theo hai chế độ:

 Giao tiếp có nối kết, nếu giữa chúng sử dụng giao thức TCP

 Giao tiếp không kết nổi, nếu sử dụng giao thức UDP

Socket là giao diện giữa chương trình và lớp vận chuyển Nó cho phép ta chọngiao thức sử dụng ở tầng vận chuyển là TCP hay UDP cho chương trình ứng dụng củamình

Bảng so sánh sự khác biện giữa hai chế độ giao tiếp có kết nối và không kết nối.

- Tồn tại kênh giao tiếp ảo giữa hai bên

giao tiếp

- Dữ liệu được gởi đi theo bảo đảm: có

kiểm tra lỗi, truyền lại gói tin lỗi hay mất,

đảm báo thứ tự của các gói tin

- Dữ liệu chính xác nhưng tốc độ truyền

- Dữ liệu không chính xác, tốc độ truyền nhanh

2.1.6 Xây dựng ứng dụng Client-Server với Socket:

Socket là phương tiện hiệu quả để xây dựng các ứng dụng theo kiến trúc Server Các ứng dụng trên Internet như Web, Mail, FTP là các ví dụ điển hình

Trang 19

Client-Chúng ta sẽ tìm hiểu về các bước cơ bản trong việc xây dựng các ứng dụngClient-Server sử dụng Socket làm phương tiện giao tiếp theo chế độ hướng kết nối(được ứng dụng trong phần gởi file và gởi hình ảnh trong chương trình).

2.1.6.1 Mô hình Client-Server sử dụng Socket ở chế độ có kết nối (TCP)

Giai đoạn 1: Server tạo Socket, gán số hiệu cổng và lắng nghe các kết nối.

Hình 2 4 Minh họa quá trình khởi tạo TCP Socket Server.

 Socket() : Server yêu cầu tạo ra một Socket để có thể sử dụng các dịch vụcủa tầng vận chuyển

 Bind() : Socket khi được tạo ra cần phải được gắn vào một port cục bộ

 Listen() : Server lắng nghe các yêu cầu kết nối từ Client trên cổng đã đượcgán

Giai đọan 2: Client tạo Socket, yêu cầu thiết lập một nối kết với Server

Hình 2 5 Mô tả quá trình khởi tạo TCP Socket Client kết nối tới Server.

 Socket() : Client yêu cầu tạo một Socket để có thể sử dụng dịch vụ của tầngvận chuyển, thông thường hệ thống thường tự động gán một port còn dảnhcho Socket của Client Nhưng ở đây ta sẽ tự động đưa vào port cho Socketcủa Client

 Connect() : Client gửi yêu cầu kết nối tới Server có địa chỉ ip và port xácđịnh

Trang 20

 Accept() : Sau khi bên phía Client kết nối tới Server thì Server sẽ chấp nhậnkết nối của Client, khi đó một kênh giao tiếp ảo được hình thành Client vàServer có thể trao đổi thông tin với nhau thông qua kênh giao tiếp ảo này.

Giai đoạn 3: Trao đổi thông tin giữa Client và Server

Hình 2 6 Mô tả quá trình truyền nhận thông tin giữa Server và Client.

 Sau khi chấp nhận yêu cầu kết nối, Server đợi Client gửi yêu cầu đến Ở đâyClient sẽ sử dụng hàm Send() gửi lần lượt các byte dữ liệu

 Server phân tích và thực thi yêu cầu Kết quả và nó gửi lại dữ liệu cho Clientbằng lệnh Send()

 Trong giai đoạn này, việc trao đổi thông tin giữa Server và Client phải tuânthủ theo giao thức ứng dụng Thông thường thì Client sẽ là bên gửi yêu cầuđến Server trước

Giai đoạn 4: Kết thúc phiên làm việc.

Hình 2 7 Mô tả kết thúc phiên làm việc giữa Client và Server.

 Việc trao đổi dữ liệu giữa Server và Client được thực hiện nhiều lần

 Kênh ảo sẽ bị xóa khi Server hoặc Client đóng Socket bằng lệnh Close().2.1.6.2 Mô hình Client-Server sử dụng Socket ở chế độ không kết nối (UDP)

Trang 21

UDP là giao thức theo phương thức không liên kết được sử dụng thay thế choTCP Nó khác với TCP, không có chức năng thiết lập liên kết và kết thúc liên kết Dovậy việc trao đổi thông tin dữ liệu là không đáng tin cậy.

Các giai đoạn thực hiện của Socket không hướng kết nối

Giai đoạn 1: Server tạo ra Socket và gán số hiệu cổng.

Hình 2 8 Mô tả quá trình khởi tạo UDP Socket Server.

 Socket(): Server yêu cầu tạo ra một Socket để sử dụng các dịch vụ của tầngvận chuyển

 Bind(): Sau khi đã khởi tạo Socket thì cần phải gắn một port cục bộ cho nó

Giai đoạn 2: Client tạo Socket.

Hình 2 9 Mô tả quá trình khởi tạo UDP Socket Client.

 Bên phía Client sẽ yêu cầu tạo ra một Socket để sử dụng dịch vụ của tầngvận chuyển

 Sau đó Client có thể Send dữ liệu tới một địa chỉ ip và port cục bộ củaServer

Giai đoạn 3: Trao đổi thông tin giữa Client và Server

Trang 22

Hình 2 10 Mô tả quá trình truyền nhận dữ liệu bằng UDP.

 Client và Server có thể trao đổi thông tin với nhau nhiều lần qua hai hàm đó

2.1.7.1 Lớp NetworkStream

Lớp này được nằm trong thư viện System.Net.Socket Lớp NetworkStream cóthể được tạo lập bằng nhiều phương thức khác nhau, nhưng một phương thức tạo lập

mà ta hay sử dụng đó là gán vào Socket của Server và Client đã được tạo lập sẵn

Socket newsock = new Socket ( AddressFamily InterNetwork, SocketType Stream, ProtocolType Tcp);

NetworkStream ns = new NetworkStream (newsock);

Một số phương thức của lớp NetworkStream

DataAvailable() true nếu có dữ liệu để đọc

BeingWrite() Bắt đầu ghi NetworkStream bất đồng bộ

Trang 23

EndWrite() Kết ghi đọc NetworkStream bất đồng bộ

Bảng 2 1 Một số phương thức của lớp NetworkStream

Chú ý : Phương thức Flush() được dùng sau mỗi phương thức Write() để đảmbảo dữ liệu được đặt vào NetworkStream sẽ lập tức gửi đến hệ thống ở xa

NetworkStream khi truyền dữ liệu cũng có gặp một số vấn đề về biên dữ liệu.Vấn đề này đã được giải quyết với hai lớp StreamReader và lớp StreamWriter.2.1.7.2 Lớp StreamReader và StreamWriter

Hai lớp này nằm trong thư viện System.IO để điều khiển đọc và ghi các thôngđiệp text từ mạng Cả hai lớp đều triển khai với đối tượng NetworkStream để xác địnhcác hệ thống đánh dấu cho thông điệp TCP

Các phương thức tạo lập lớp StreamRead và StreamWriter, trong đó mộtphương thức tạo lập mà ta hay được sử dụng nhất đó là gắn hai lớp trên vào lớpNetworkStream đã được tạo lập từ trước

Socket newsock = new Socket(AddressFamily InterNetwork , SocketType Stream , ProtocolType Tcp )

NetworkStream ns = new NetworkStream( newsock )

StreamReader nr = new StreamReader( ns )

StreamWriter nw = new StreamWriter( ns )

Một số phương thức của lớp StreamRead

StreamReader

Không gỡ bỏ nó khỏi Stream

StreamRead trở lên cho tới khi bắt gặp ký tựxuống dòng đầu tiên

Trang 24

ToString() Tạo ra một chuỗi mô tả đối tượng Stream.

Bảng 2 2 Một số phương thức lớp StreamRead

Một số phương thức của lớp StreamWriter

Lớp StreamWriter cũng có nhiều phương thức kết hợp với nó, một số phương thức củalớp StreamRead cũng có trong đối tượng StreamWriter, ngoài ra nó còn có một số phươngthức giêng dưới đây

StreamWriter ra Stream

WriterLine() Gửi dữ liệu cùng với ký tự xuống dòng ra

2.1.8.1.TCPClient

TCPClient được thiết kế nhằm hỗ trợ cho việc viết các ứng dụng TCP Clientđược dễ dàng

Bảng các thành viên của lớp TCPClient

Phương thức khởi tạo Mô tả

TcpClient() Tạo một đối tượng TcpClient Chưa đặt thông số gì

TcpClient(IPEndPoint

)

Tạo một TcpClient và gắn cho nó một EndPoint cục bộ.(Gán địa chỉ máy cục bộ và số hiệu cổng để sử dụngtrao đổi thông tin về sau)

TcpClient(String,Int32

)

Tạo một đối tượng TcpClient và kết nối đến một máy cóđịa chỉ và số hiệu cổng được truyền vào RemoteHost cóthể là địa chỉ IP chuẩn hoặc tên máy

Các thuộc tính Mô tả

Available Cho biết số byte đã nhận về từ mạng và có sẵn để đọc

Trang 25

Connected Trạng thái cho biết đã kết nối được đến Server hay

Kết nối đến một máy TCP khác có Tên và số hiệu cổng

GetStream() Trả về NetworkStream để từ đó giúp ta gửi hay nhận dữ

liệu (Thường làm tham số khi tạo StreamReader vàStreamWriter để gửi và nhận dữ liệu dưới dạng xâu kýtự)

Khi đã gắn vào StreamReader và StreamWriter rồi thì ta

có thể gửi và nhận dữ liệu thông qua các phương thứcReadline, writeline tương ứng của các lớp này

Bảng 2 4 Các thành viên của lớp TCPClient.

Từ các thành viên của lớp TcpClient ở trên ta thấy rằng, việc kết nối và thựchiện gửi nhận rất đơn giản Theo các trình tự sau:

 Bước 1: Tạo một đối tượng TcpClient

Bước 2: Kết nối đến máy chủ (Server) dùng phương thức Connect.

 Bước 3: Tạo 2 đối tượng StreamReader (Receive)và StreamWriter

(Send) và "nối" với GetStream của TCPClient.

Bảng các thành viên của lớp TCPListener

Trang 26

Phương thức khởi tạo Mô tả

TcpListener ( Int32) Tạo một TcpListener và lắng nghe tại cổng chỉ

AcceptSocket( ) Chấp nhận một yêu cầu kết nối đang chờ

AcceptTcpClient() Chấp nhận một yêu cầu kết nối đang chờ (Ứng

dụng sẽ dừng tại lệnh này cho đến khi nào cómột kết nối đến – “Blocking”)

Pending() Cho biết liệu có kết nối nào đang chờ đợi khôngStart() Bắt đầu lắng nghe các yêu cầu kết nối

Bảng 2 5 Các phương thành viên của lớp TCPListener.

2.1.8.3 UDPClient

Giao thức UDP (User Datagram Protocol hay User Define Protocol) là một giaothức phi kết nối (connectionless) có nghĩa là một bên có thể gửi dữ liệu cho bên kia màkhông cần biết là bên đó đã sẵn sàng hay chưa? (Nói cách khác là không cần thiết lậpkết nối giữa hai bên khi tiến hành trao đổi thông tin) Giao thức này không tin cậybằng giao thức TCP nhưng tốc độ lại nhanh và dễ cài đặt Ngoài ra, với giao thức UDP

ta còn có thể gửi các gói tin quảng bá (Broadcast) cho đồng thời nhiều máy

Trong NET, lớp UDPClient (nằm trong namesapce System.Net.Sockets) đónggói các chức năng của giao thức UDP

Bảng các thành viên của lớp UDPClient

Phương thức khởi tạo Mô tả

UdpClient () Tạo một đối tượng (thể hiện) mới của lớp

UDPClient

UdpClient (AddressFamily) Tạo một đối tượng (thể hiện) mới của lớp

UDPClient Thuộc một dòng địa chỉ(AddressFamily) được chỉ định

UdpClient (Int32) Tạo một UdpClient và gắn (bind) một cổng cho nó.UdpClient (IPEndPoint) Tạo một UdpClient và gắn (bind) một IPEndpoint

(gán địa chỉ IP và cổng) cho nó

Trang 27

BeginReceive() Nhận dữ liệu Không đồng bộ từ máy ở xa

BeginSend() Gửi không đồng bộ dữ liệu tới máy ở xa

Connect() Thiết lập một Default remote host

EndReceive() Kết thúc nhận dữ liệu không đồng bộ ở trên

EndSend() Kết thúc việc gửi dữ liệu không đồng bộ ở trên

Receive (ref IPEndPoint) Nhận dữ liệu (đồng bộ) do máy ở xa gửi (Đồng bộ

có nghĩa là các lệnh ngay sau lệnh Receive chỉđược thực thi nếu Receive đã nhận được dữ liệu

về Còn nếu nó chưa nhận được – dù chỉ một chút– thì nó vẫn cứ chờ (blocking))

Send() Gửi dữ liệu (đồng bộ) cho máy ở xa

Bảng 2 6 các thành viên của lớp UDPClient.

2.1.9 Lập trình Socket bất đồng bộ

Ở phần đầu của báo cáo chúng ta đã lập trình Socket trong chế độ blocking.Socket blocking sẽ chờ mãi cho đến khi hoàn thành nhiệm vụ của nó Trong khi nó bịblocking thì các chức năng khác của chương trình không thực hiện được

Khi lập trình Windows thì lúc gọi một phương thức bị blocking thì toàn bộchương trình sẽ đứng lại và không thể thực hiện các chức năng khác được Do đó việclập trình bất đồng bộ là cần thiết để cho chương trình khỏi bị treo

Lớp AsyncCallback cung cấp các phương thức để bắt đầu một chức năng bấtđồng bộ và cung cấp một phương thức delegate để gọi chức năng bất đồng bộ kết thúc

Các phương thức bất đồng bộ trong Socket chia các chức năng mạng làm haiphần

 Một phương thức Begin bắt đầu các chức năng mạng và đăng ký phươngthức AsyncCallback

 Một phương thức End hoàn thành chức năng mạng khi phương thứcAsyncCallback được gọi

Trang 28

BeginConnect() Kết nối đến thiết bị ở xa EndConnect()

BeginReceive() Nhận dữ liệu từ Socket EndReceive()

BeginReceiveFrom() Nhận dữ liệu từ thiết bị ở xa EndReceiveFrom()

BeginSend() Gửi dữ liệu từ Socket EndSend ()

BeginSendTo() Gửi dữ liệu đến thiết bị ở xa EndSendTo()

Bảng 2 7 Các phương thức của lập trình Socket bất đồng bộ.

2.1.9.1 Thành lập kết nối

Phương thức dùng để thành lập kết nối với thiết bị ở xa phụ thuộc vào chươngtrình đóng vai trò là Server hay Client Nếu là Server thì phương thức BeginAccept()được dùng, còn bên Client thì phương thức BeginConnect() được sử dụng

Phương thức BeginAccept() và EndAccept()

Server.BeginAccept( new AsyncCallback (CallAccept), Server);

Socket s = (Socket)ia.AsyncState;

Server = s.EndAccept(ia);

Sau khi phương thức BeginAccept() kết thúc, phương thức AsyncCallback địnhnghĩa sẽ được gọi khi kết nối xảy ra Phương thức AsyncCallback phải bao gồmphương thức EndAccept() để kết thúc việc chấp nhận Socket Sau đây là định dạng củaphương thức EndAccept()

Phương thức Beginconnect() và EndConnect()

_clientsocket.BeginConnect(_ipep,

new AsyncCallback (CallPConnect), _clientsocket);

_clientsocket.EndConnect(ia);

2.1.9.2 Trao đổi dữ liệu

Sau khi Server và Client đã thiết lập kết nối, ta có thể thực hiện việc trao đổi dữliệu giữa Server và Client

Phương thức BeginSend() và EndSend()

_ServerSocket.BeginSend(data, 0, data.Length, SocketFlags None, new AsyncCallback (SendcmdMessage), _ServerSocket);

Socket s = ( Socket ) ia.AsyncState;

Trang 29

.Net Remoting là cơ chế giao tiếp giữa các đối tượng (object) mà không cùngthuộc một Process Giúp các lớp đối tượng thuộc các ứng dụng khác nhau có thể liênlạc được với nhau Các đối tượng của các ứng dụng này có thể được thiết lập trên cùngmột máy tính hay các máy tính khác nhau và được giao tiếp từ xa thông qua các giaothức kết nối như HTTP,TCP.

Microsft .Net Remoting được giới thiệu từ .Net Framework 1.1 cùng vớiWebservice Cung cấp các kĩ thuật cho phép một đối tượng này truy xuất đến một đốitượng khác nằm ở các Application Domain khác nhau

Hình 2 11 Mô hình trao đổi thông tin của Net Remoting.

2.2.2 Remote Objects trong NET Remoting

Nếu như ở một chương trình đơn thì các đối tượng sẽ cùng thuộc trong ứngdụng đó, và chúng dễ dàng giao tiếp được với nhau; đây có thể được coi là LocalObjects Tuy nhiên nếu các đối tượng lại thuộc những ứng dụng khác nhau (cácApplication domain khác nhau) thì cần có những Remote Object để giao tiếp với nhau.Remote Object có thể được dẫn xuất từ MarshalByRefObject hay sử dụng

[Serializable] tag hoặc bằng cách tạo các giao diện ISerializable

Các loại Remote Object:

Trong NET Remoting, có hai cơ chế để tạo instance của Remote Object rồi từ

đó thực thi request Đó là Singleton và Singlecall Tùy vào mục đích sử dụng, nhu cầucủa ứng dụng mà server có thể khai báo theo cơ chế

WellKnownObjectMode.SingleCall, hay WellKnownObjectMode.Singleton

 Single Call Object: Remote Object sẽ được sinh ra, thực thi request, trảlời cho client, sau đó Object này vẫn được lưu lại chứ không bị hủy đi.Đến khi nào process chạy chương trình Server kết thúc thì instance nàymới bị trình hốt rác Garbage Collection hốt đi

Trang 30

 Singleton Object: Ngược lại với Single Call, khi khai báo Remote Object

là Singleton thì Remote Object sẽ được khởi tạo và hủy đi đối với mỗilần nhận request từ phía Client Cơ chế này tương tự như mô hình NETWebservice truyền thống

 Client-Activated Objects (CAO): Thuộc kiểu “Server-side object”,chúng chỉ được kích hoạt mỗi khi có request đến từ Client Khi mộtClient gửi một request tới Server sử dụng toán tử “new”, một thông điệp

sẽ được gửi tới Remote Application Server sau đó sẽ tạo ra một Instancecủa lớp được yêu cầu, và trả về một ObjRef cho Client Application.2.2.3.Domain

Trong NET, khi một ứng dụng được nạp vào trong bộ nhớ, một tiến trình đượctạo ra, và trong quá trình này, một miền ứng dụng (Application Domain) cũng đượctạo ra Trên thực tế, ứng dụng này sẽ được nạp vào Application Domain Mỗi ứngdụng có thuộc các Application Domain khác nhau, vì thế nếu chúng muốn giao tiếpđược với nhau thì phải sử dụng Remoting chứ không thể giao tiếp trực tiếp với nhauđược Các Application Domain có thể cùng thuộc một process hoặc khác process

2.2.4.Channel

Trong kỹ thuật Net Remoting thì Channel được hiểu như là một kênh để giaotiếp giữa Client và Server Một Object từ Client sẽ thông qua Channel để giao tiếp vớiObject phía Server, Channel sẽ truyền tải những Message từ hai phía Như giới thiệuphía trên thì có hai Channel chính là TcpChannel và HttpChannel tương ứng với cácgiao thức TCP và HTTP Ngoài ra, TcpChannel và HttpChannel đều có khả năngExtend thành những Custom Channel

Các nguyên tắc khi thiết lập một Channel

 Cần có ít nhất một Channel được đăng ký với NET Remoting trước khiRemote Object được gọi Và các Channels này cần đăng ký trước cácRemote Object

 Channel được đăng ký trong mỗi Application Domain hoặc nhiềuApplication Domain thuộc một Process Khi Process kết thúc thì cácChannel này cũng tự động được hủy đi

 Không thể đăng ký các Channel khác nhau trên cùng một port thuộccùng một máy tính mặc dù các Channel này có thể ở các ApplicationDomai khác nhau Khi thiết lập nhiều Channel trên cùng một máy tínhthì chúng cần listen ở các port khác nhau

 Client liên lạc với Remote Object thông qua các kênh đã đăng ký bằngviệc gọi các RegisterChannel trên lớp ChannelService

2.2.5 Object Activation

Trang 31

Server Actived Object chỉ được tạo ra ở lần đầu tiên Client thiết lập cuộc gọi tớicác Remote Method Hay nói cách khác, Khi một Client yêu cầu tạo ra các RemoteObject thì chỉ các proxy cục bộ được tạo ra ở Client, còn Remote Object thực tế nằmtrên Server Các Remote Object này sẽ được khởi tạo ở lần đầu tiên Client thiếp lậpcuộc gọi cho Server Ví dụ tạo ra các Proxy như sau.

2.2.6 Client Activated Objects

Đối tượng Client Activated Object được tạo ra mỗi trên Server ngay lập tức mỗikhi có request từ Client hoặc cũng có thể tạo ra bằng từ khóa new hoặc

Trang 32

 Singleton object được dùng để tham chiếu đến những đối tượng cùngtrên một server, và bất kỳ thay đổi của Client cũng sẽ “visible” (hiệnhữu) với những Client khác Ví dụ như trong hệ điều hành Windows, khimột chương trình thay thì các Client Program khác cũng biết được Dữliệu sẽ được lưu trên máy chủ và được truy cập bởi tất cả các Client.

 Chúng ta sử dụng SingleCall khi muốn cung cấp một môi trường

“stateless” (Kiểu giống của Web services truyền thống

 Chúng ta sử dụng Client Activation nếu đối đượng cần phải được duy trìtrạng thái kết nối liên tục, trao đổi thông tin với các client khác

2.2.7 Tạo một Remotable Object

Một Remote Object là một đối tượng được kế thừa từ lớp MarshalByRefObject.Trong C#, khi tạo một lớp thư viện mới Ta Add thêm lớp có tênMarshalByRefObject như đã nói ở trên Khai báo using System.Runtime.Remoting để

có thể sử dụng được các TcpChannel hay HttpChannel

2.3 Lập trình sự kiện trong Windows.

Trong lập trình sự kiện của Windows, mỗi khi sự kiện sảy ra, một phương thứcđược gọi để thực thi dựa trên sự kiện đó như trong hình dưới đây

Trang 33

Hình 2 12 Lập trình sự kiện trong Windows.

2.3.1 Sử dụng Event và Delegate

Evetn là một thông điệp được gửi bởi một đối tượng mô tả một hoạt động mà

nó diễn ra Thông điệp này xác định hoạt động và truyền các dữ liệu cần thiết cho hoạtđộng Event có thể mô tả hoạt động nào đó, chẳng hạn như hoạt động click mộtButton, hoạt động nhận và gửi dữ liệu trên Socket Event sender không cần thiết phảibiết đối tượng nào sẽ điều khiển thông điệp sự kiện mỗi khi nó được gửi thông qua hệthống Windows Nó để cho bộ phận sự kiện đăng ký với hệ thống Windows và thôngbáo kiểu sự kiện mà bộ phận nhận sự kiện muốn nhận như hình minh họa sau

Hình 2 13 Gửi và nhận sự kiện trong Windows.

Bộ nhận sự kiện được xác định trong hệ thống Windows bởi một con trỏ lớpđược gọi là Delegate Một Delegate là một lớp nó giữ tham chiếu đến một phươngthức mà phương thức này điều khiển sự kiện được nhận Khi hệ thống Windows nhận

sự kiện, nó kiểm tra xem thử có Delegate nào đăng ký để xử lý nó không Nếu cóDelegate đăng ký để sử lý sự kiện, thông điệp sự kiện được truyền vào phương thứcđược định nghĩa bởi Delegate Sau khi phương thức hoàn tất, hện thống Windows sẽ

xử lý sự kiện tiếp theo xảy ra cho tới khi sự kiện kết thúc chương trình được phát ra

Trang 34

2.4 Lập trình đa luồng.

2.4.1 Khái niệm đa luồng (Thread)

Một luồng (Thread) là một chuỗi liên tiếp những sự thực thi trong chương

trình Trong một chương trình C#, việc thực thi bắt đầu bằng phương thức main() vàtiếp tục cho đến khi kết thúc hàm main() Cấu trúc này rất hay cho những chương trình

có một chuỗi xác định những nhiệm vụ liên tiếp Nhưng thường thì một chương trìnhcần làm nhiều công việc hơn vào cùng một lúc Ví dụ trong Internet Explorer khi tađang tải một trang web thì ta nhấn nút back hay một link nào đó, để làm việc nàyInternet Explorer sẽ phải làm ít nhất là 3 việc:

 Lấy dữ liệu được trả về từ Internet cùng với các tập tin đi kèm

 Thể hiện trang Web

 Xem người dùng có nhập để làm thứ gì khác không

Để đơn giản vấn đề này ta giả sử Internet Explorer chỉ làm hai công việc:

 Trình bày trang Web

 Xem người dùng có nhập gì không

Để thực hành việc này ta sẽ viết một phương thức dùng để lấy và thể hiện trangWeb Giả sử rằng việc trình bày trang Web mất nhiều thời gian (do phải thi hành cácđoạn javascript hay các hiệu ứng nào đó …) Vì vậy sau một khoảng thời gian ngắnkhoảng 1/12 giây, phương thức sẽ kiểm tra xem người dùng có nhập gì không Nếu cóthì nó sẽ đuơc xử lí, nếu không thì việc trình bày trang sẽ được tiếp tục Và sau 1/12giây việc kiểm tra sẽ được lặp lại Tuy nhiên viết phương thức này thì rất phức tạp do

đó ta sẽ dùng kiến trúc event trong Window nghĩa là khi việc nhập xảy ra hệ thống sẽthông báo cho ứng dụng bằng cách đưa ra một event Ta sẽ cập nhật phương thức đểcho phép dùng các event:

 Ta sẽ viết một bộ xử lí event để đáp ứng đối với việc nhập của ngườidùng

 Ta sẽ viết một phương thức để lấy và trình bày dữ liệu Phương thức nàyđược thực thi khi ta không làm bất cứ điều gì khác

Ta hãy xem cách phương thức lấy và trình bày trang web làm việc: đầu tiên nó

sẽ tự định thời gian Trong khi nó đang chạy, máy tính không thể đáp ứng việc nhậpcủa người dùng Do đó nó phải chú ý đến việc định thời gian để gọi phương thức kiểmtra việc nhập của người dùng, nghĩa là phương thức vừa chạy vừa quan sát thời gian.Bên cạnh đó nó còn phải quan tâm đến việc lưu trữ trạng thái trước khi nó gọi phươngthức khác để sau khi phương thức khác thực hiện xong nó sẽ trả về đúng chỗ nó đãdừng Vào thời Window 3.1 đây thực sự là những gì phải làm để xử lí tình huống này.Tuy nhiên ở NT3.1 và sau đó là Windows 95 trở đi đã có việc xử lí đa luồng điều nàylàm việc giải quyết vấn đề tiện lợi hơn Dưới đây chúng ta sẽ tìm hiểu một vài lớp cơ

Trang 35

bản trong ngôn ngữ lập trình C# và vấn đề đồng bộ hóa (Synchronization) trong lậptrình đa luồng.

2.4.2 Tham khảo thư viện System.Thread

Namespace System.Threading cung cấp một số kiểu dữ liệu cho phép bạn thựchiện lập trình đa luồng Ngoài việc cung cấp những kiểu dữ liệu tượng trưng cho mộtluồng cụ thể nào đó, namespace này còn định nghĩa những lớp có thể quản lý mộtcollection các luồng (ThreadPool), một lớp Timer đơn giản (không dựa vào GUI) vàcác lớp cung cấp truy cập được đồng bộ vào dữ liệu được chia sẽ sử dụng

Các lớp thành viên Mô tả

Interlocked Lớp này dùng cung cấp truy cập đồng bộ hóa vào dữ liệu được chia

sẽ sử dụng (shared data)

Moniter Lớp này cung cấp việc đồng bộ hóa các đối tượng luồng sử dụng

khóa chốt (lock) và tín hiệu chờ (wait signal)

Mutex Lớp này cung cấp việc đồng bộ hóa sơ đẳng có thể được dùng đối

với inter process synchronization

Thread Lớp này tượng trưng cho một luồng được thi hành trong lòng

Common Language Runtime Sử dụng lớp này bạn có khả năng bổsung những luồng khác trong cùng AppDomain

ThreadPool Lớp này quản lý những luồng có liên hệ với nhau trong cùng một

Process nào đó

Timer Cho biết một delegate có thể được triệu gọi vào một lúc được khai

báo nào đó Tác vụ wait được thi hành bởi luồng trong thread pool.WaitHandle Lớp này tượng trưng cho tất cả các đối tượng đồng bộ hóa (cho

phép multiple wait) vào lúc chạy

ThreadStart Lớp này là một delegate chỉ về hàm hành sự nào đó phải được thi

hành đầu tiên khi một luồng bắt đầu

TimerCallBack Delegate đối với Timer

WaitCallBack Lớp này là một delegate định nghĩa hàm hành sự kêu gọi lại

(callback) đối với ThreadPool user work item

Bảng 2 8 Một số lớp thuộc tính của thư viện System.Thread.

2.4.2 Lớp Thread

Lớp đơn giản nhất trong tất cả các lớp thuộc Namespace System.Threading làlớp Thread Lớp này tượng trưng cho một vỏ bọc hướng đối tượng bao quanh một lộtrình thi hành trong lòng một AppDomain nào đó Lớp này định nghĩa một số hàmthực thi (cả static lẫn shared) cho phép bạn tạo mới những luồng từ luồng hiện hành,cũng như cho Sleep, Stop hay Kill một luồng nào đó

Các thành phần Static Mô tả

Trang 36

CurrentThread Thuộc tính read-only này trả về một quy chiếu về luồng hiện

đang chạy

GetData() Đi lấy vị trí từ slot được khai báo trên luồng hiện hành đối với

domain hiện hành trong luồng

SetData() Cho đặt để trị lên slot được khai báo trên luồng hiện hành đối

với domain hiện hành trong luồngGetDomain()

GetDomainID()

Đi lấy một qui chiếu về AppDomain hiện hành (hoặc mã nhậndiện ID của domain này) mà luồng hiện đang chạy trên đó.Sleep() Cho ngưng luồng hiện hành trong một thời gian nhất định được

khai báo

Bảng 2 9 Các thành phần static của lớp Thread.

Ngoài ra lớp Thread cũng hỗ trợ các thành viên cung cấp đối tượng

Các lớp thành viên Mô tả

IsAlive Thuộc tính này trả về một trị boolean cho biết liệu xem luồng đã

khởi đông hay chưa

IsBackground Đi lấy hoặc đặt để giá trị cho biết liệu xem luồng là một luồng nền

hay không

Name Thuộc tính này cho phép bạn thiết lập một tên văn bản mang tính

thân thiện đối với luồng

Priority Đi lấy hoặc đặt để ưu tiên của một luồng Có thể được gán một trị

lấy từ enumeration ThreadPriority (chẳng hạn Normal, Lowest,Highest, BelowNormal, AboveNormal)

ThreadState Đi lấy hoặc đặt để tình trạng của luồng Có thế được gán từ

enumeration ThreadState (chẳng hạn Unstarted, Running,WaitSleepJoin, Suspended, SuspendRequested, AbortRequested,Stopped)

Interrup() Cho ngưng chạy luồng hiện hành

Join() Yêu cầu luồng chờ đối với luồng bị ngưng chạy

Resume() Tiếp tục lại đối với một luồng bị ngưng chạy

Start() Cho bắt đầu thi hành luồng được khai báo bởi delegate ThreadStart.Suspend() Cho ngưng chạy một luồng Nếu luồng đã bị ngưng rồi, một triệu

gọi hàm Suspend() sẽ không có tác dụng

Bảng 2 10 Các thành viên cấp đối tượng của lớp Thread.

2.4.3 Thao tác với luồng

Trang 37

Luồng được thao tác bằng cách dùng lớp Thread nằm trong thư việnSystem.Threading Một thể hiện của luồng đại diện cho một luồng Ta có thể tạo cácluồng khác bằng cách khởi tạo một đối tượng Thread.

Giả sử rằng ta đang viết 1 trình biên tập hình ảnh đồ hoạ, và người dùng yêucầu thay đổi độ sâu của màu trong ảnh Ta bắt đầu khởi tạo một đối tượng luồng nhưsau:

// entryPoint được khai báo trước là 1 delegate kiểu ThreadStart

Thread depthChangeThread = new Thread (entryPoint);

Đoạn mã trên biểu diễn một hàm khởi tạo của Thread với một thông số chỉ địnhđiểm nhập của một luồng Đó là phương thức nơi luồng bắt đầu thi hành Trong tìnhhuống này ta dùng thông số là delegate, một delegate đã được định nghĩa trongSystem.Threading gọi là ThreadStart, chữ kí của nó như sau:

public delegate void ThreadStart ();

Thông số ta truyền cho hàm dựng phải là 1 delegate kiểu này Ta bắt đầu luồngbằng cách gọi phương thức Thread.Start(), giả sử rằng ta có phương thức ChanColor():

void ChanColor()

{

// xử lí để thay đổi màu

}

Sắp xếp lại ta có đoạn mã sau

ThreadStart entryPoint = new ThreadStart (ChangeColorDepth);

Thread depthChangeThread = new Thread (entryPoint);

depthChangeThread.Name = “Depth Change Thread”;

depthChangeThread.Start();

Sau điểm này, cả hai luồng sẽ chạy đồng bộ với nhau

Trong đoạn mã này ta đăng kí tên cho luồng bằng cách dùng thuộc tínhThread.Name Không cần thiết làm điều này nhưng nó có thể hữu ích

Lưu ý vì điểm đột nhập vào luồng (trong ví dụ này là ChanColor() ) không thểlấy bất kì thông số nào Ta sẽ phải tìm một cách nào đó để truyền thông số cho phươngthức nếu cần Cách tốt nhất là dùng các trường thành viên của lớp mà phương thức này

là thành viên Cũng vậy phương thức không thể trả về bất cứ thứ gì

Mỗi lần ta bắt đầu một luồng khác, ta cũng có thể đình chỉ, hồi phục hay bỏ qua

nó Đình chỉ nghĩa là cho luồng đó ngủ (sleep) - nghĩa là không chạy trong 1 khoảngthời gian Sau đó nó thể đưọc phục hồi, nghĩa là trả nó về thời diểm mà nó bị định chỉ.Nếu luồng đưọc bỏ, nó dừng chạy Window sẽ huỷ tất cả dữ liệu mà liên hệ đến luồng

đó, để luồng không thể được bắt đầu lại Tiếp tục ví dụ trên, ta giả sử vì lí do nào đó

Trang 38

luồng giao diện người dùng trình bày một hộp thoại cho người dùng cơ hội để đình chỉtạm thời sự đổi tiến trình Ta sẽ soạn mã đáp ứng trong luồng main :

ThreadAbortException là một lớp biệt lệ đặc biệt mà không bao giờ được xử lí.Nếu luồng đó thực thi mã bên trong khối try, bất kì khối finally sẽ được thực thi trướckhi luồng bị huỷ Sau khi huỷ luồng ta có thể muốn đợi cho đến khi luồng thực sự bịhuỷ trước khi tiếp tục luồng khác ta có thể đợi bằng cách dùng phương thức join():

depthChangeThread.Abort();

depthChangeThread.Join();

Join() cũng có một số overload khác chỉ định thời gian đợi Nếu hết thời giannày việc thi hành sẽ được tiếp tục Nếu một luồng chính muốn thi hành một vài hànhđộng trên nó, nó cần một tham chiếu đến đối tượng luồng mà đại diện cho luồng riêng

Nó có thể lấy một tham chiếu sử dụng thuộc tính static -CurrentThread- của lớpThread:

Thread myOwnThread = Thread CurrentThread;

Có hai cách khác nhau mà ta có thể thao tác lớp Thread:

 Ta có thể khởi tạo một đối tượng luồng, mà sẽ đại diện cho luồng đangchạy và các thành viên thể hiện của nó áp dụng đến luồng đang chạy

 Ta có thể gọi một số phương thức static, những phương thức này sẽ ápdụng đến luồng mà ta thực sự đang gọi phương thức từ nó Một phươngthức static mà ta muốn Sleep(), đơn giản đặt luồng đang chạy ngủ mộtkhoảng thời gian, sau đó tiếp tục

2.4.4 Đồng bộ hóa (Synchronization) trong lập trình đa luồng

2.4.4.1 Đồng bộ hóa

Đôi khi có thể bạn muốn điều khiển việc truy cập vào một nguồn lực, chẳng hạncác thuộc tính hoặc các hàm của một đối tượng, làm thế nào chỉ một mạch trình đượcphép thay đổi hoặc sử dụng nguồn lực đó mà thôi Việc đồng bộ hóa được thể hiệnthông qua một cái khóa được thiết lập trên đối tượng, ngăn không cho luồng nào đótruy cập khi mạch trình đi trước chưa xong công việc

Trang 39

Trong phần này, ta sẽ là quen với cơ chế đồng bộ hóa mà Common LanguageRuntime cung cấp: lệnh lock Nhưng trước tiên, ta cần mô phỏng một nguồn lực đượcchia sẽ sử dụng bằng cách sử dụng một biến số nguyên đơn giản: counter

Để bắt đầu, ta khai báo biến thành viên và khởi gán về zero:

int counter = 0;

Bài toán được đặt ra ở đây như sau: luồng thứ nhất sẽ đọc trị counter (0) rồi gángiá trị này cho biến trung gian (temp) Tiếp đó tăng trị của temp rồi Sleep một khoảngthời gian Luồng thứ nhất xong việc thì gán trị của temp trả về cho counter và cho hiểnthị trị này Trong khi nó làm công việc, thì luồng thứ hai cũng thực hiện một công việcgiống như vậy Ta cho việc này lập này khoảng 1000 lần Kết quả mà ta chờ đợi là hailuồng trên đếm lần lượt tăng biến counter lên 1 và in ra kết quả 1, 2, 3, 4 … tuy nhiên

ta sẽ xét đoạn chương trình dưới đây và thấy rằng kết quả hoàn toàn khác với những gì

private int counter = 0;

static void Main( string [] args)

Console WriteLine( "Start thread {0}" , t1.Name);

Thread t2 = new Thread ( new ThreadStart (Incrementer));

Trang 40

Console WriteLine( "Thread {0} Incrementer: {1}" ,

Thread CurrentThread.Name, counter);

Ngày đăng: 02/06/2015, 17:51

Nguồn tham khảo

Tài liệu tham khảo Loại Chi tiết
[1]. Ingo Rammer, Advanced .Net Remoting (C# Edition), Impressions Book and Journal Services, Inc (2002) Sách, tạp chí
Tiêu đề: Advanced .Net Remoting (C# Edition)
Tác giả: Ingo Rammer
Nhà XB: Impressions Book and Journal Services, Inc
Năm: 2002
[6]. Joe Mayo, C# 3.0 UNLEASHED , Copyright © 2008 by Pearson Education, Inc Sách, tạp chí
Tiêu đề: C# 3.0 UNLEASHED
Tác giả: Joe Mayo
Nhà XB: Pearson Education, Inc
Năm: 2008
[8]. Wei-Meng Lee , C# 2008 Programmer’s Reference , Wiley Publishing, Inc (2009) Sách, tạp chí
Tiêu đề: C# 2008 Programmer’s Reference
Tác giả: Wei-Meng Lee
Nhà XB: Wiley Publishing, Inc
Năm: 2009
[9]. Joseph Albahari and Ben Albahari, C# 4.0 IN A NUTSHELL, O’Reilly Media, Inc Sách, tạp chí
Tiêu đề: C# 4.0 IN A NUTSHELL
Tác giả: Joseph Albahari, Ben Albahari
Nhà XB: O’Reilly Media, Inc
[13].Nhóm tác giả, Giáo trình lập trình mạng với Java, Tổng hợp diễn đàn Đại học Sách, tạp chí
Tiêu đề: Giáo trình lập trình mạng với Java
Tác giả: Nhóm tác giả
Nhà XB: Tổng hợp diễn đàn Đại học
[14].Nhóm tác giả, Giáo trình lập trình mạng với C#, Trường Đại học Đà Lạt Sách, tạp chí
Tiêu đề: Giáo trình lập trình mạng với C#
Tác giả: Nhóm tác giả
Nhà XB: Trường Đại học Đà Lạt
[15].Văn Thiên Hoàng, Giáo trình lập trình mạng, Trường Đại học Công Nghệ Đại học Quốc Gia TP.Hồ Chí Minh Sách, tạp chí
Tiêu đề: Giáo trình lập trình mạng
Tác giả: Văn Thiên Hoàng
Nhà XB: Trường Đại học Công Nghệ Đại học Quốc Gia TP.Hồ Chí Minh
[16].Nguyễn Quang Hoan, Giáo trình xử lý ảnh, Học viện công nghệ Bưu Chính Viễn Thông Sách, tạp chí
Tiêu đề: Giáo trình xử lý ảnh
Tác giả: Nguyễn Quang Hoan
Nhà XB: Học viện công nghệ Bưu Chính Viễn Thông
[21].Nguyễn Tấn Thuận, Lập trình ứng dụng Windows From trong C#, Học viện công nghệ thông tin NIT Sách, tạp chí
Tiêu đề: Lập trình ứng dụng Windows From trong C#
Tác giả: Nguyễn Tấn Thuận
Nhà XB: Học viện công nghệ thông tin NIT
[2]. Andrew Krowczyk, Vinod Kumar, Nauman Laghari, Tim Parker, Srinivasa Sivakumar, Professional_.NET_Network_Programming, Wrox Press Ltd Khác
[3]. Brent Rector, Introduction to .NET Remoting, Wise Owl Consulting, Inc (2004) Khác
[4]. Fiach Reid, Network programming in .NET with C# and VB.NET (Digital Press), Elsevier’s Science & Technology Rights Department in Oxford (2004) Khác
[5]. Richard Blum, Sybex_-_Csharp_Network_Programming, Sybex © 2003 Khác
[7]. Simon Robinson, Christian Nagel, Jay Glynn, Morgan Skinner, Karli Watson, Bill Evjen, Professional C# Third Edition, Wiley Publishing, Inc (2004) Khác
[10].Đào Lưu Duy, Bài giảng lập trình mạng với C#, Sách điện tử Khác
[11].Ngô Bá Hùng, Nguyễn Công Huy, Giáo trình lập trình mạng với Java, Khoa Công Nghệ Thông Tin trường Đại học Cần Thơ Khác
[12].Nguyễn Cao Đạt, Bài giảng lập trình mạng, Trường Đại học Bách Khoa TP.Hồ Chí Minh Khác
[17].Nguyễn Hùng Cường, Bài thực hành xử lý ảnh với C#, Trường Đại học Công Nghiệp Hà Nội Khác
[18].Nhóm tác giả, Căn bản XML, Trung tâm công nghệ phần mềm Thừa Thiên Huế Khác
[19].Nguyễn Hà Giang, Lập trình Windows C#, Trường Đại học Khoa học tự nhiên Đại học Quốc Gia Hà Nội Khác

HÌNH ẢNH LIÊN QUAN

Hình 2. 1: Chức năng của Socket. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 2. 1: Chức năng của Socket (Trang 16)
Hình 2. 2. Sơ đồ giao tiếp các máy tính khác nhau. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 2. 2. Sơ đồ giao tiếp các máy tính khác nhau (Trang 17)
Hình 2. 3: Các chế độ giao tiếp các tầng mạng khác nhau. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 2. 3: Các chế độ giao tiếp các tầng mạng khác nhau (Trang 18)
Hình 2. 7. Mô tả kết thúc phiên làm việc giữa Client và Server. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 2. 7. Mô tả kết thúc phiên làm việc giữa Client và Server (Trang 20)
Hình 2. 11. Mô hình trao đổi thông tin của .Net Remoting. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 2. 11. Mô hình trao đổi thông tin của .Net Remoting (Trang 29)
Hình 2. 12. Lập trình sự kiện trong Windows. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 2. 12. Lập trình sự kiện trong Windows (Trang 33)
Hình 2. 14. Kết quả chương trình không sử dụng đồng bộ hóa. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 2. 14. Kết quả chương trình không sử dụng đồng bộ hóa (Trang 41)
Hình 2. 15. Kết quả chương trình sử dụng đồng bộ hóa. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 2. 15. Kết quả chương trình sử dụng đồng bộ hóa (Trang 42)
Hình 2. 18. Mô tả ma trận điểm ảnh. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 2. 18. Mô tả ma trận điểm ảnh (Trang 46)
Hình 3. 1. Mô hình phân cấp chức năng. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 3. 1. Mô hình phân cấp chức năng (Trang 55)
Hình 3. 2. Hình minh họa chức năng chia sẻ màn hình. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 3. 2. Hình minh họa chức năng chia sẻ màn hình (Trang 56)
Hình 3. 3. Các nội dung giảng dạy có trên màn hình các máy học viên. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 3. 3. Các nội dung giảng dạy có trên màn hình các máy học viên (Trang 56)
Hình 3. 4. Minh họa chia sẻ màn hình cho toàn bộ học viên. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 3. 4. Minh họa chia sẻ màn hình cho toàn bộ học viên (Trang 57)
Hình 3. 6. Minh họa chức năng chia sẻ màn hình. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 3. 6. Minh họa chức năng chia sẻ màn hình (Trang 58)
Hình 3. 7. Mô hình luồng dữ liệu. - BÀI BÁO CÁO THỰC TẬP-XÂY DỰNG PHẦN MỀM LỚP HỌC ẢO TRONG MẠNG LAN
Hình 3. 7. Mô hình luồng dữ liệu (Trang 59)

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w