Trong lập trình socket, sử dụng mô hình bất đồng bộ (asynchronous programming) có nhiều lợi ích. Đầu tiên, khi sử dụng mô hình bất đồng bộ, chương trình có thể tiếp tục thực hiện các tác vụ khác trong khi đang chờ đợi phản hồi từ socket, giúp tăng hiệu quả và thời gian đáp ứng của ứng dụng. Thứ hai, mô hình bất đồng bộ cho phép xử lý đồng thời nhiều kết nối cùng lúc, do đó giảm thời gian chờ đợi của người dùng và cải thiện trải nghiệm người dùng. Cuối cùng, mô hình bất đồng bộ cũng giúp giảm tải cho máy chủ khi nhiều yêu cầu đến cùng lúc, do đó tăng khả năng chịu tải của hệ thống. Vì những lý do này, mô hình bất đồng bộ đã trở thành một lựa chọn phổ biến trong lập trình socket và được sử dụng rộng rãi trong các ứng dụng mạng hiện đại.
CƠ SỞ LÝ THUYẾT
Lập trình đồng bộ (Synchronous Programming)
Lập trình đồng bộ (synchronous) là cách lập trình mà các hoạt động của chương trình sẽ được thực hiện tuần tự
Trong mô hình lập trình quen thuộc của chúng ta, các công việc được thực hiện theo trật tự thời gian Công việc sắp xếp trước thực hiện xong mới đến lượt công việc tiếp theo
Giả sử, có ba công việc được sắp xếp theo trình tự T1, T2, T3; thời gian thực hiện T1 là t1 giây, với T2 là t2 giây, T3 là t3 giây
Khi nhiệm vụ T1 đã được bắt đầu thực hiện thì phải chờ T1 kết thúc, T2 mới được bắt đầu (sau t1 s) Một khi T2 bắt đầu thì phải chờ T2 kết thúc, T3 mới được bắt đầu (sau t1 + t2 s) Tổng thời gian thực hiện của cả ba nhiệm vụ là t1 + t2 + t3 s
Mô hình lập trình theo đó các công việc bắt đầu và kết thúc theo đúng trình tự thời gian như trên được gọi là lập trình đồng bộ.
Lập trình bất đồng bộ
Lập trình bất đồng bộ là cách lập trình cho phép các hoạt động thực hiện không theo tuần tự Có thể các đoạn code ở dưới chạy trước đoạn code viết ở phía trên (bất đồng bộ), các hoạt động không phải đợi lẫn nhau Bởi vì có nhiều threads nên khi xử lý các hoạt động có thời gian dài thì main thread (UI) vẫn có thể hoạt động do các thread là riêng biệt
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Giả sử (vẫn 3 nhiệm vụ T1, T2, T3 như trên) bây giờ chúng ta không chờ T1 kết thúc mà bắt đầu luôn T2 Ngay sau khi bắt đầu T2 chúng ta bắt đầu luôn T3
Trong mô hình này, nhiệm vụ sau không phải chờ nhiệm vụ trước kết thúc nữa Tổng thời gian thực hiện của ba nhiệm vụ không phải là t1+t2+t3 nữa mà nhỉnh hơn thời gian thực hiện nhiệm vụ dài nhất Rõ ràng mô hình này có lợi thế hơn về thời gian thực hiện
Mô hình trong đó các nhiệm vụ không phải tuân thủ theo trình tự thời gian như trên được gọi là mô hình bất đồng bộ (asynchronous) Như vậy mô hình bất đồng bộ cũng cho phép thực hiện song song nhiều nhiệm vụ cùng lúc
Trong lập trình socket, mô hình bất đồng bộ được sử dụng rất phổ biến ở cả client và server Đối với server , mô hình này cho phép xử lý đồng thời nhiều client và phát huy tốt khả năng xử lý song song của server Đối với client, nó giúp chương trình không bị treo giao diện khi thực hiện các nhiệm vụ kéo dài
Trước khi Asynchronous programing ra đời ở những phiên bản cũ hơn của Net, chúng ta có công nghệ lập trình đa luồng (multiple thread) Đây là hai khái niệm và mô hình khác nhau, mặc dù cùng hướng tới mục tiêu tương tự Lập trình đa luồng là kỹ thuật cho phép chương trình thực hiện nhiều luồng (thread) cùng một lúc, mỗi luồng thực hiện một tác vụ riêng biệt Các luồng sẽ chia sẻ tài nguyên của chương trình như bộ nhớ, CPU, và các thiết bị nhập xuất Lập trình đa luồng được sử dụng để tăng tốc độ thực thi chương trình bằng cách sử dụng đồng thời nhiều CPU hoặc nhân của CPU để thực hiện các tác vụ đồng thời Trong khi đó, lập trình bất đồng bộ không phải là lập trình đa luồng Thay vì sử dụng nhiều luồng, lập trình bất đồng bộ cho phép các tác vụ đơn lẻ
LẬP TRÌNH MẠNG ĐỀ TÀI 03
(single-threaded) thực hiện đồng thời và không chờ đợi các tác vụ khác hoàn thành trước khi thực hiện tác vụ tiếp theo bằng cách sử dụng các hàm bất đồng bộ (asynchronous functions) hoặc các gọi hệ thống không đồng bộ (asynchronous system calls), mỗi tác vụ được thực hiện trên cùng một luồng Kỹ thuật này thường được sử dụng trong các ứng dụng web, khi cần xử lý các yêu cầu HTTP đến từ nhiều người dùng khác nhau cùng một lúc, và trong các ứng dụng desktop khi cần tương tác với các tác vụ I/O như đọc/ghi dữ liệu từ đĩa cứng.
So sánh lập trình đồng bộ và lập trình bất đồng bộ
Ưu điểm của lập trình đồng bộ: Các hoạt động xảy ra tuần tự nên có thể dễ quản lý, dễ debug và phát hiện vấn đề khi xảy ra lỗi
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Vấn đề: Nếu thời gian chạy các hoạt động đồng bộ xảy ra quá dài thì UI sẽ bị lock (đứng chương trình) do UI và các hoạt động đồng bộ cùng thuộc về 1 thread
Ví dụ: Đơn giản nhất là khi ta làm việc với api lấy danh sách users từ database hay từ file Trong trường hợp data quá lớn thì việc api này sẽ trả về rất lâu(thời gian chờ lâu) Nếu ta lập trình đồng bộ (synchronous) thì chương trình sẽ bị đứng (block UI) do ta phải đợi gọi xong api thì khi đó thread duy nhất UI mới được giải phóng và làm việc khác
Vậy thread là gì: như hình minh họa ở trên 1 process(hay còn được hiểu là 1 chương trình) sẽ bao gồm nhiều threads Mỗi thread có thể thực hiện các hoạt động khác nhau
Ví dụ: Khi ta mở 1 ứng dụng web nghe nhạc Ta vừa có thể play nhạc, vừa có thể làm các hành động khác: pause, next, back, view list songs bởi vì mỗi hành động là một thread(một luồng riêng biệt)
LẬP TRÌNH MẠNG ĐỀ TÀI 03
NHÓM 07 6 Ưu điểm của lập trình bất đồng bộ: Bởi vì không bị block thread và các hoạt động có thể không phải đợi nhau nên khi xử lý các tác vụ có thời gian thực hiện lâu không bị đứng chương trình, đem lại trải nghiệm người dùng tốt
Vấn đề: Bởi vì các hoạt động thực hiện không theo thứ tự nên ta phải quản lý các hành động này một cách cẩn thận Ví dụ như khi bạn xử lý hành động submit 1 form, đầu tiên phải validate dữ liệu, sau đó mới tới phần xử lý Nếu như quản lý không tốt phần bất đồng bộ có thể dẫn tới: Phần xử lý chạy trước cả phần validate dữ liệu -> có thể gây ra lỗi nghiêm trọng.
Lập trình bất đồng bộ trong C#.Net
Lập trình bất đồng bộ thường được sử dụng trong các xử lý tiềm ẩn blocking, giống như truy cập tới website, việc truy cập tài nguyên trên web đôi lúc là chậm trễ Ngoài ra có một số xử lý khác nên được xây dựng bất động bộ như: Làm việc trên file, ảnh,
Từ Net Framework 4.5 và Windows Runtime sẽ có một số phương thức trong các APIs hỗ trợ bất đồng bộ như ở dưới:
✓ Working with files: StorageFile, StreamWriter, StreamReader, XmlReader
✓ Working with images: MediaCapture, BitmapEncoder, BitmapDecoder
✓ WCF programming: Synchronous and Asynchronous Operations
LẬP TRÌNH MẠNG ĐỀ TÀI 03
C# hỗ trợ nhiều mô hình lập trình bất đồng bộ để giúp giải quyết các vấn đề về hiệu suất và độ trễ trong các ứng dụng Dưới đây là các mô hình lập trình bất đồng bộ chính trong C#:
Asynchronous Programming Model (APM): là mô hình kế thừa sử dụng giao diện
IAsyncResult để cung cấp hành vi không đồng bộ Trong mẫu này, các thao tác không đồng bộ yêu cầu Begin và End các phương thức (ví dụ: BeginWritevà EndWriteđể triển khai thao tác ghi không đồng bộ) Đây là một mô hình lập trình bất đồng bộ cổ điển Trong mô hình này, bạn định nghĩa một hàm gọi lại (callback function) mà sẽ được gọi khi tác vụ bất đồng bộ hoàn thành Hàm gọi lại này được truyền vào phương thức bất đồng bộ làm tham số
Event-based Asynchronous Pattern (EAP): là mô hình kế thừa dựa trên sự kiện để cung cấp hành vi không đồng bộ Nó yêu cầu một phương thức có Async hậu tố và một hoặc nhiều sự kiện, loại ủy quyền trình xử lý sự kiện và EventArg loại có nguồn gốc Đây là một mô hình lập trình bất đồng bộ chuẩn được định nghĩa bởi Microsoft Trong mô hình này, bạn sử dụng các sự kiện để thông báo về tiến trình của tác vụ bất đồng bộ Các sự kiện này được kích hoạt khi tác vụ bắt đầu, tiến trình thay đổi hoặc kết thúc EAP đã được giới thiệu trong NET Framework 2.0
Task-based Asynchronous Pattern (TAP): Đây là mô hình lập trình bất đồng bộ mới nhất được định nghĩa bởi Microsoft Trong mô hình này, bạn sử dụng đối tượng Task để đại diện cho tác vụ bất đồng bộ và sử dụng từ khóa async và await để lập trình bất đồng bộ TAP đã được giới thiệu trong NET Framework 4
APM ra đời đầu cùng với những phiên bản Net đầu tiên EAP ra đời sau và hoạt động dựa trên sự kiện APM và EAP không được khuyến khích sử dụng nữa, TAP xuất hiện gần đây nhất và thay đổi hoàn toàn cách lập trình bất đồng bộ TAP được xây dựng trên bộ thư viện TPL (Task Parallel Library, dùng cho xử lí song song)
Task-based Asynchronous Pattern (TAP) là một mô hình lập trình bất đồng bộ trong C# được sử dụng để thực hiện các tác vụ đồng thời mà không chặn luồng chính
LẬP TRÌNH MẠNG ĐỀ TÀI 03
NHÓM 07 8 của ứng dụng TAP cho phép ta thực hiện các phương thức bất đồng bộ bằng cách sử dụng từ khóa "async" và "await" trong C#.
Lập trình bất đồng bộ mô hình TAP với từ khóa async và await trong C#.Net
Task-based Asynchronous Pattern (TAP) là một mô hình lập trình để thực hiện các tác vụ bất đồng bộ trong NET Framework và NET Core TAP giúp ta giải quyết các vấn đề liên quan đến lập trình đa luồng, như sự cố xung đột giữa các luồng, tăng hiệu suất ứng dụng và tăng khả năng phản hồi của ứng dụng
Khi sử dụng TAP, chúng ta sẽ tạo ra một tác vụ Task để thực hiện công việc bất đồng bộ Tác vụ này sẽ chứa một hoặc nhiều công việc cần thực hiện, ví dụ như truy vấn cơ sở dữ liệu, tải tệp từ internet, hoặc tính toán phức tạp Khi một phương thức được đánh dấu với từ khóa "async", nó cho phép phương thức trả về một Task hoặc Task Khi một phương thức trả về một Task, nó chỉ định rằng phương thức đó là bất đồng bộ và sẽ trả về một kết quả trong tương lai
Ta sử dụng từ khóa await để đợi tác vụ hoàn thành mà không chặn luồng chính của ứng dụng Khi một phương thức được gọi và chứa từ khóa "await", nó cho phép chương trình tiếp tục thực hiện các công việc khác trong khi chờ đợi tác vụ bất đồng bộ được hoàn thành Khi tác vụ được hoàn thành, chương trình sẽ tiếp tục thực hiện các dòng lệnh tiếp theo
Tại thời điểm tác vụ được đợi, nó có thể hoàn thành bất kỳ lúc nào và kết quả sẽ được trả về cho phương thức gọi Trong quá trình đợi, luồng chính của ứng dụng có thể tiếp tục thực hiện các tác vụ khác mà không bị chặn
Các tác vụ có thể chạy trên các luồng khác nhau, tùy thuộc vào cách triển khai của phương thức Khi một tác vụ được hoàn thành, kết quả của nó sẽ được trả về cho phương thức gọi thông qua một đối tượng Task Ta có thể sử dụng kết quả này để thực hiện các tác vụ tiếp theo hoặc hiển thị nó trên giao diện người dùng
LẬP TRÌNH MẠNG ĐỀ TÀI 03
NHÓM 07 9 Điều này giúp cho chương trình không bị chặn trong khi đợi các tác vụ bất đồng bộ hoàn thành và giúp cải thiện hiệu suất của ứng dụng TAP cũng cho phép xử lý các ngoại lệ được ném ra từ các tác vụ bất đồng bộ, giúp đơn giản hóa mã lỗi và làm cho mã dễ đọc hơn
Ví dụ về sử dụng phương thức bất đồng bộ:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Các số trong sơ đồ tương ứng với các bước sau, được bắt đầu khi một phương thức gọi gọi phương thức bất đồng bộ:
1 Calling method gọi và chờ GetUrlContentLengthAsync phương thức bất đồng bộ
2 GetUrlContentLengthAsync tạo một phiên bản HttpClient và gọi phương thức bất đồng bộ GetStringAsync để tải xuống nội dung của trang web dưới dạng chuỗi
3 Một cái gì đó xảy ra trong GetStringAsync đó đình chỉ tiến trình của nó Có lẽ nó phải đợi một trang web tải xuống hoặc một số hoạt động chặn khác Để tránh chặn tài nguyên, GetStringAsync hãy nhường quyền kiểm soát cho người gọi nó,
GetStringAsync trả về một Task, ở đâu Tresult là một chuỗi và GetUrlContentLengthAsync gán tác vụ cho getStringTask biến Nhiệm vụ đại diện cho quá trình đang diễn ra đối với lệnh gọi đến GetStringAsync, với cam kết tạo ra một giá trị chuỗi thực tế khi công việc hoàn tất
4 Vì getStringTask chưa được chờ đợi, GetUrlContentLengthAsync nên có thể tiếp tục với công việc khác mà không phụ thuộc vào kết quả cuối cùng từ
GetStringAsync Công việc đó được thể hiện bằng một cuộc gọi đến phương thức đồng bộ DoIndependentWork
5 DoIndependentWork là một phương thức đồng bộ thực hiện công việc của nó và trả về trình gọi của nó
6 GetUrlContentLengthAsync đã hết công việc mà nó có thể thực hiện mà không có kết quả từ getStringTask GetUrlContentLengthAsync next muốn tính toán và trả về độ dài của chuỗi đã tải xuống, nhưng phương thức không thể tính giá trị đó cho đến khi phương thức có chuỗi
Do đó, GetUrlContentLengthAsync sử dụng toán tử đang chờ để tạm dừng tiến trình của nó và nhường quyền kiểm soát cho phương thức được gọi là
GetUrlContentLengthAsync trả về a Taskcho người gọi Nhiệm vụ thể hiện lời hứa tạo ra một kết quả số nguyên có độ dài của chuỗi đã tải xuống
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Bên trong phương thức gọi, mẫu xử lý vẫn tiếp tục Người gọi có thể thực hiệncông việc khác không phụ thuộc vào kết quả từ GetUrlContentLengthAsynctrước khi chờ kết quả đó hoặc người gọi có thể chờ ngay lập tức Phương thức gọi đang chờ GetUrlContentLengthAsyncvà GetUrlContentLengthAsyncđang chờ GetStringAsync
7 GetStringAsynchoàn thành và tạo ra một kết quả chuỗi Kết quả chuỗi không được trả về GetStringAsynctheo cách mà bạn có thể mong đợi (Hãy nhớ rằng phương thức đã trả về một tác vụ ở bước 3.) Thay vào đó, kết quả chuỗi được lưu trữ trong tác vụ đại diện cho việc hoàn thành phương thức, getStringTask Toán tử chờ lấy kết quả từ getStringTask Câu lệnh gán gán kết quả đã truy xuất cho contents
8 Khi GetUrlContentLengthAsynccó kết quả chuỗi, phương thức có thể tính toán độ dài của chuỗi Sau đó, công việc của GetUrlContentLengthAsynccũng hoàn tất và trình xử lý sự kiện đang chờ có thể tiếp tục Trong ví dụ đầy đủ ở cuối chủ đề, bạn có thể xác nhận rằng trình xử lý sự kiện truy xuất và in giá trị của kết quả độ dài Nếu bạn chưa quen với lập trình không đồng bộ, hãy dành một phút để xem xét sự khác biệt giữa hành vi đồng bộ và không đồng bộ Phương thức đồng bộ trả về khi công việc của nó hoàn tất (bước 5), nhưng phương thức không đồng bộ trả về giá trị tác vụ khi công việc của nó bị tạm dừng (bước 3 và 6) Khi phương thức async cuối cùng hoàn thành công việc của nó, tác vụ được đánh dấu là đã hoàn thành và kết quả, nếu có, được lưu trữ trong tác vụ.
Lập trình Socket bất đồng bộ TCPIP Server với từ khóa async _await trong C#
Mô hình bất đồng bộ là một phương pháp lập trình cho phép các hoạt động I/O (input/output) được thực hiện mà không cần chờ đợi các hoạt động I/O hoàn thành trước khi thực hiện các hoạt động khác Trong lập trình socket, mô hình bất đồng bộ thường được sử dụng để tối ưu hóa thời gian phản hồi của các ứng dụng socket
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Các ứng dụng socket truyền thống thường sử dụng mô hình đồng bộ, trong đó các hoạt động I/O được thực hiện theo thứ tự tuần tự, một sau một Điều này có nghĩa là nếu một hoạt động I/O mất nhiều thời gian để hoàn thành, thì tất cả các hoạt động khác phải đợi cho đến khi hoạt động đó hoàn thành trước khi được thực hiện Điều này dẫn đến thời gian phản hồi chậm và hiệu suất kém
Với mô hình bất đồng bộ, các hoạt động đầu I/O ra được thực hiện độc lập với nhau, mà không cần phải chờ đợi các hoạt động khác hoàn thành trước Khi một hoạt động đầu I/O ra được gọi, nó sẽ được thực hiện trong nền và ứng dụng tiếp tục thực hiện các hoạt động khác Khi hoạt động I/O hoàn thành, ứng dụng sẽ được thông báo và có thể tiếp tục thực hiện các hoạt động khác
Mô hình bất đồng bộ có thể cải thiện hiệu suất và thời gian phản hồi của các ứng dụng socket, đặc biệt là trong các ứng dụng có nhiều kết nối đồng thời Nó cũng giúp tăng khả năng chịu tải của các ứng dụng socket, cho phép chúng xử lý được nhiều kết nối cùng lúc mà không ảnh hưởng đến hiệu suất của hệ thống
Khi sử dụng mô hình bất đồng bộ, chương trình có thể tiếp tục thực hiện các tác vụ khác trong khi đang chờ đợi phản hồi từ socket, giúp tăng hiệu quả và thời gian đáp ứng của ứng dụng Mô hình bất đồng bộ cho phép xử lý đồng thời nhiều kết nối cùng lúc, do đó giảm thời gian chờ đợi của người dùng và cải thiện trải nghiệm người dùng Mô hình bất đồng bộ cũng giúp giảm tải cho máy chủ khi nhiều yêu cầu đến cùng lúc, do đó tăng khả năng chịu tải của hệ thống
LẬP TRÌNH MẠNG ĐỀ TÀI 03
PHÂN TÍCH VIDEO: 03 TCPIP SERVER ASYNCHRONOUS SOCKET
Section Intro Asynchronous socket programming with async await in C# Net
Từ khóa async và await đã được giới thiệu trong Net Framework 4.5
Các phương pháp không chặn đặc biệt cũng được giới thiệu
Các lớp trợ giúp socket: TCPListener, TCPClient
StreamReader & StreamWriter với các luồng mạng
Class library, tangible course takeaway
Tạo 1 class: Trong solution add một new Project:
Chọn class libary (.Net Framework):
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Kết nối thư viện với form:
Example Disadvantage of synchronous IO in C# Net
Trên visual studio 2019, sử dụng Windows Forms App (.Net Framework) và tiến hành chọn Framework trên 4.5:
Tạo form với 1 nút button “Start” có chức năng khi nhấn vào chương trình mới bắt đầu thực hiện:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Sử dụng đoạn code Server TCP ở bài trước:
Server đang tiến hành lắng nghe Client kết nối tới và in ra màn hình dòng lệnh “About to accept incoming connection”
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Server lắng nghe và đợi để chấp nhận yêu cầu nếu có client kết nối vào:
Tuy nhiên, nếu như chưa có client nào kết nối hoặc quá trình kết nối bị gián đoạn, dẫn đến thời gian chờ quá lâu, thì chương trình sẽ bị đứng và không phản hồi Vì chương trình thực hiện bằng mô hình đồng bộ nên các lệnh được thực thi tuần tự Do đó, server sẽ lắng nghe, đến khi nào có chấp nhận kết nối mới thực hiện các hành động khác, tất cả các hoạt động khác sẽ bị block và phải đợi cho đến khi listenerSocket.Accept() đó hoàn thành trước khi được thực hiện
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Tiến hành cho client kết nối vào, server chấp nhận kết nối, chương trình phản hồi trở lại và tiếp tục thực hiện các lệnh phía sau:
Như vậy, nếu sử dụng mô hình đồng bộ trong lập trình socket thì trong quá trình nhận kết nối từ client trên server, chương trình không thể làm bất cứ điều gì khác ngoài việc chờ đợi dẫn đến chương trình bị đứng và các luồng khác bị block Điều này dẫn đến thời gian phản hồi chậm và hiệu suất kém Do đó, để cải thiện hiệu suất và tối ưu hóa thời gian phản hồi của các ứng dụng socket thì trong lập trình socket, sẽ sử dụng mô hình bất đồng bộ.
Accepting a TCPClient Connection Asynchronously with await keyword in C#
Sử dụng async và await để tiến hành lập trình sever theo mô hình bất đồng bộ
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Khi thêm async vào StartListeningForIncomingConnection() thì trở thành phương thức bất đồng bộ:
Thêm từ khóa “await” cho phương thức AcceptTcpClientAsync() Như vậy, từ khóa
“await” nó cho phép chương trình tiếp tục thực hiện các công việc khác trong khi chờ đợi server lắng nghe và chấp nhận kết nối bất đồng bộ được hoàn thành Khi tác vụ được hoàn thành, chương trình sẽ tiếp tục thực hiện các dòng lệnh tiếp theo.
Demo Accept TCPClient Asynchronously
Tiến hành đặt 2 debug tại 2 vị trí in ra màn hình và tiến hành debug từng dòng:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
NHÓM 07 19 Ấn dòng tiếp theo: Ấn dòng tiếp theo: Ấn dòng tiếp theo: Ấn dòng tiếp theo: Đến đây chương trình bắt đầu thực thi việc lắng nghe và chấp nhận kết nối từ client Tuy nhiên, trong quá trình này chương trình không bị đứng như 2.2 mà vẫn tiếp tục phản hồi:
Ta tiếp tục ấn vào button thì chương trình tiếp tục quay lại debug đầu:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Như vậy, hoạt động chấp nhận kết nối từ client được thực hiện độc lập, mà không cần phải chờ đợi các hoạt động khác hoàn thành trước, nó sẽ được thực hiện trong nền và ứng dụng tiếp tục thực hiện các hoạt động khác Khi hoạt động kết nối hoàn thành, ứng dụng sẽ được thông báo và có thể tiếp tục thực hiện các hoạt động tiếp theo Do đó, chương trình sẽ không bị đứng hay block các luồng khác.
Continuously Accept Client Connections, Exception Handling in C# async Method: 20 2.6 Use System.Net.Socket.NetworkStream _ StreamReader to read data from client
Sử dụng vòng lặp while để việc lắng nghe kết nối và in kết quả được lặp lại, với mục đích nhận kết nối từ nhiều client thay vì chỉ một client như trước
Dùng Try catch() để xử lý ngoại lệ Khi không client kết nối vào thì thông báo
LẬP TRÌNH MẠNG ĐỀ TÀI 03
2.6 Use System.Net.Socket.NetworkStream _ StreamReader to read data from client:
Tạo ra phương thức bất đồng bộ TakeCareOfTCPClient(returnedByAccept) để đọc thông điệp từ client gửi về:
Thêm từ khóa asyns để trở thành phương thức bất đồng bộ, đồng thời sử dụng try catch() để xử lí ngoại lệ:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Sử dụng System.Net.Socket.NetworkStream _ StreamReader để đọc thông điệp và gán giá trị đầu bằng null:
Sử dụng phương thức bất đồng bộ ReadAsync để đọc thông điệp nhận được từ client Phương thức này trả về một Task, đại diện cho số lượng byte được đọc được trả về và gán nó vào nRet, trong đó buff là mảng byte sẽ chứa dữ liệu được đọc, 0 là vị trí bắt đầu trong mảng byte để lưu dữ liệu được đọc, buff.Length count lượng byte tối đa sẽ được đọc:
Trong trường hợp số lượng byte được đọc là 0 thì tức là client đã ngắt kết nối với server:
Tiếp theo, chuyển mảng buff từ kiểu byte thành kiểu chuỗi và in ra màn hình kết quả:
Sử dụng vòng lặp while để nhận hết các thông điểm được gửi:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Demo Read Data On Network Stream and Endless Accept async in C#.Net
Đọc dữ liệu từ 1 client: Đọc dữ liệu từ nhiều client:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Sử dụng chương trình client của bài trước để conncet vào server và gửi thông điệp:
How to Handle Multiple Network Clients on Server in C# Net
Tạo một danh sách các máy client:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Xây dựng phương thức khởi tạo:
Sau khi lắng nghe và chấp nhận kết nối từ client thì tiến hành add client vào danh sách trên:
Tạo hàm removeClient để khi có client ngắt kết nối thì chương trình sẽ thông báo:
Nếu số lượng số lượng byte được đọc là 0 có nghĩa là client đó đã ngắt kết nối và sẽ gọi hàm removeClient ra:
Tạo thêm 1 textbox và button send all để nhập và gửi dữ liệu từ server cho client:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Nhập thông điệp vào textbox, sau đó nhân button sendall, Khi buton send all được click sẽ gọi phương thức bất đồng bộ SendToAll() và gán thông điệp vào phương thức:
Dùng try catch() đẻ xử lý ngoại lệ và dùng if để xử lý trường hợp thông điệp rỗng:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
Chuyển thông điệp từ kiểu string sang byte Duyệt tuần tự qua từng client trong danh sách và tiến hành gửi thông điệp đó cho client bằng phương thức bất đồng bộ WritrAsync.
Demo Send Data to Multiple Network Clients from List at Once, SendAll Method
Cho 3 client connect vào server, sau đó tắt đi 1 client thì số lượng client còn là 2:
Gửi thông điệp cho nhiều client cùng một lúc:
LẬP TRÌNH MẠNG ĐỀ TÀI 03
How to Stop Listening for New Connections and Disconnect Client Sockets Properly: 28 2.11 Demo TcpListener.Stop and TcpClient.Close Calls to Stop Server
Xây dựng button stop khi click vào sẽ gọi hàm StopServer:
Nếu có client kết nối thì dừng server, sau đó chạy tuần tự qua tất cả các client và tiến hàng đóng tất cả lại:
2.11 Demo TcpListener.Stop and TcpClient.Close Calls to Stop Server:
Khi ấn button stop thì chương trình server dừng lại, mọi kết nối được ngắt và client bị đóng:
LẬP TRÌNH MẠNG ĐỀ TÀI 03