Pages

25 thg 2, 2010

Tạo TCP server hỗ trợ đa tiểu trình

Khi muốn tạo một TCP server có thể cùng lúc xử lý nhiều TCP client, chúng ta sử dụng phương thức AcceptTcpClient của lớp TcpListener . Mỗi khi có một client mới kết nối đến, khởi chạy một tiểu trình mới để xử lý yêu cầu và gọi TcpListener.AcceptTcpClient...

Khi muốn tạo một TCP server có thể cùng lúc xử lý nhiều TCP client, chúng ta sử dụng phương thức AcceptTcpClient của lớp TcpListener. Mỗi khi có một client mới kết nối đến, khởi chạy một tiểu trình mới để xử lý yêu cầu và gọi TcpListener.AcceptTcpClient lần nữa.

Một endpoint TCP (địa chỉ IP và port) có thể phục vụ nhiều kết nối. Thực ra, hệ điều hành đảm đương phần lớn công việc giùm bạn. Những gì bạn cần làm là tạo một đối tượng thợ (worker object) trên server để xử lý mỗi kết nối trong một tiểu trình riêng.

Xét lớp TCP client và TCP server, bạn có thể dễ dàng chuyển server này thành một server hỗ-trợ đa tiểu trình để thực hiện nhiều kết nối cùng một lúc. Trước hết, tạo một lớp để tương tác với một client:

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.IO;
  5. using System.Threading;
  6. using SharedComponent;
  7. public class ClientHandler {
  8. private TcpClient client;
  9. private string ID;
  10. public ClientHandler(TcpClient client, string ID) {
  11. this.client = client;
  12. this.ID = ID;
  13. }
  14. public void Start() {
  15. // Thu lấy network stream.
  16. NetworkStream stream = client.GetStream();
  17. // Tạo BinaryWriter để ghi ra stream.
  18. BinaryWriter w = new BinaryWriter(stream);
  19. // Tạo BinaryReader để đọc từ stream.
  20. BinaryReader r = new BinaryReader(stream);
  21. if (r.ReadString() == ClientMessages.RequestConnect) {
  22. w.Write(ServerMessages.AcknowledgeOK);
  23. Console.WriteLine(ID + ": Connection completed.");
  24. while (r.ReadString() != ClientMessages.Disconnect) {}
  25. Console.WriteLine(ID + ": Disconnect request received.");
  26. w.Write(ServerMessages.Disconnect);
  27. }else {
  28. Console.WriteLine(ID + ": Could not complete connection.");
  29. }
  30. // Đóng socket.
  31. client.Close();
  32. Console.WriteLine(ID + ": Client connection closed.");
  33. Console.ReadLine();
  34. }
  35. }

Kế tiếp, thay đổi mã lệnh của server sao cho nó lặp liên tục, tạo ra các thể hiện ClientHandler mới khi cần và chạy chúng trong các tiểu trình mới. Dưới đây là mã lệnh đã được sửa đổi:

  1. public class TcpServerTest {
  2. private static void Main() {
  3. TcpListener listener =new TcpListener(IPAddress.Parse("127.0.0.1"), 8000);
  4. Console.WriteLine("Server: About to initialize port.");
  5. listener.Start();
  6. Console.WriteLine("Server: Listening for a connection...");
  7. int clientNum = 0;
  8. while (true) {
  9. try {
  10. // Đợi yêu cầu kết nối, và trả về một TcpClient.
  11. TcpClient client = listener.AcceptTcpClient();
  12. Console.WriteLine("Server: Connection accepted.");
  13. // Tạo một đối tượng mới để xử lý kết nối này.
  14. clientNum++;
  15. ClientHandler handler =new ClientHandler(client, "Client " +clientNum.ToString());
  16. // Khởi động đối tượng này làm việc trong
  17. // một tiểu trình khác.
  18. Thread handlerThread =new Thread(new ThreadStart(handler.Start));
  19. handlerThread.IsBackground = true;
  20. handlerThread.Start();
  21. // (Bạn cũng có thể thêm Handler và HandlerThread vào
  22. // một tập hợp để theo dõi các phiên client.)
  23. }catch (Exception err) { Console.WriteLine(err.ToString());
  24. }
  25. }
  26. }
  27. }

Dưới đây là transcript phía server của một phiên làm việc với hai client:

Server: About to initialize port.

Server: Listening for a connection...

Server: Connection accepted.

Client 1: Connection completed.

Server: Connection accepted.

Client 2: Connection completed.

Client 2: Disconnect request received.

Client 2: Client connection closed.

Client 1: Disconnect request received.

Client 1: Client connection closed.

Bạn có thể thêm mã lệnh vào server để nó theo vết các đối tượng thợ hiện hành trong một tập hợp. Làm như thế sẽ cho phép server hủy bỏ các tác vụ này nếu nó cần phải đóng và chỉ được phép một số tối đa client cùng một lúc.

0 nhận xét:

Đăng nhận xét

Powered By Blogger