Bài 3: Giải phẫu vòng đời của một kết nối Socket
Ở Bài 2, chúng ta đã hiểu sự khác biệt giữa hai "tính cách" TCP và UDP. Nhưng làm thế nào để một chương trình phần mềm (như trình duyệt của bạn) có thể "nói chuyện" được với một máy chủ (như Google hay Facebook) thông qua hệ điều hành?
Trong bài học này, chúng ta sẽ mổ xẻ vòng đời của một kết nối Socket — tức là chuỗi các bước hệ thống (system calls) mà cả Client và Server phải thực hiện để thiết lập, duy trì và đóng một kết nối mạng.
1. Mô hình Client - Server: Phân định vai trò
Trong lập trình mạng hướng kết nối (TCP), hai phía tham gia có vai trò hoàn toàn khác nhau:
-
Server (Máy chủ): Luôn ở trong trạng thái "chờ đợi", luôn mở sẵn một cánh cửa ở một Port cố định để sẵn sàng tiếp đón bất kỳ Client nào gõ cửa.
-
Client (Máy khách): Là bên "chủ động" khởi tạo cuộc gọi, tìm đến địa chỉ của Server và yêu cầu thiết lập kết nối.
Hãy xem chi tiết từng bước diễn ra bên trong hệ điều hành của cả hai bên.
2. Vòng đời phía Server (Lắng nghe & Tiếp nhận)
Để một Server có thể phục vụ kết nối, nó phải trải qua 4 bước cơ bản sau:
Plaintext
[ socket() ] ──► [ bind() ] ──► [ listen() ] ──► [ accept() ] ──► (Chờ & Nhận dữ liệu)
-
socket()(Khởi tạo đầu cắm):- Server yêu cầu hệ điều hành cấp phát một Socket File Descriptor. Lúc này, hệ điều hành chỉ tạo ra một cấu trúc dữ liệu trống trong RAM chứ chưa biết nó dùng để làm gì hay gắn với cổng nào.
-
bind()(Gán địa chỉ IP và Port):-
Server gắn Socket vừa tạo với một địa chỉ IP cụ thể của máy và một Port cố định (ví dụ: Port
8080). -
Ẩn dụ: Giống như việc bạn đăng ký rõ ràng số nhà và tên đường để bưu điện biết đường gửi thư đến.
-
-
listen()(Chuyển sang trạng thái lắng nghe):-
Server ra lệnh cho hệ điều hành: "Hãy chuyển socket này sang trạng thái sẵn sàng lắng nghe các yêu cầu kết nối từ bên ngoài đi tới."
-
Lúc này, Server giống như một nhân viên lễ tân ngồi trực ở quầy, sẵn sàng chờ điện thoại reo.
-
-
accept()(Chấp nhận kết nối):- Khi có một Client gọi tới, Server thực thi hàm
accept(). Hệ điều hành sẽ hoàn tất quá trình "bắt tay 3 bước" (3-Way Handshake) của TCP và sinh ra một Socket hoàn toàn mới riêng biệt chỉ để phục vụ riêng cho Client đó. Socket ban đầu vẫn tiếp tục đứng ở Port cũ để chờ đón các Client khác.
- Khi có một Client gọi tới, Server thực thi hàm
3. Vòng đời phía Client (Chủ động kết nối)
Phía Client đơn giản hơn rất nhiều vì nó không cần phải mở cổng lắng nghe ai cả:
Plaintext
[ socket() ] ──► [ connect() ] ──► (Trao đổi dữ liệu)
-
socket()(Khởi tạo đầu cắm):- Client cũng gọi hàm tạo socket tương tự như Server để có một đầu cắm phía client.
-
connect()(Yêu cầu kết nối):-
Client gọi hàm
connect(), truyền vào IP của Server và Port của Server. -
Hệ điều hành của Client sẽ gửi gói tin
SYNđi qua mạng Internet tìm đến Server. Khi Server phản hồi bằngSYN-ACKvà Client đáp lại bằngACK(quá trình bắt tay 3 bước hoàn tất), kết nối chính thức được thiết lập thành công!
-
4. Giai đoạn trao đổi dữ liệu & Đóng kết nối
Sau khi kết nối đã được thiết lập giữa Client và Server (thông qua accept và connect), vòng đời chuyển sang giai đoạn giao tiếp:
-
Truyền nhận dữ liệu (
read/writehoặcsend/recv):- Lúc này, lập trình viên có thể đọc và ghi dữ liệu qua Socket y hệt như thao tác với một file thông thường trên ổ cứng. Dữ liệu từ Client đẩy vào
write()sẽ bay qua đường truyền mạng và xuất hiện ở hàmread()phía Server.
- Lúc này, lập trình viên có thể đọc và ghi dữ liệu qua Socket y hệt như thao tác với một file thông thường trên ổ cứng. Dữ liệu từ Client đẩy vào
-
Đóng kết nối (
close):- Khi đã hoàn tất công việc, một trong hai bên (hoặc cả hai) gọi hàm
close()để chấm dứt kết nối, giải phóng tài nguyên RAM và các Port mạng trên hệ điều hành.
- Khi đã hoàn tất công việc, một trong hai bên (hoặc cả hai) gọi hàm
Tổng kết
Vòng đời của một kết nối Socket là một điệu nhảy nhịp nhàng: Server chuẩn bị sân khấu (socket -> bind -> listen -> accept), Client chủ động tiến tới (socket -> connect), và sau đó hai bên tự do trò chuyện trước khi đóng máy.
Hiểu rõ sơ đồ các bước này là tiền đề tối quan trọng để bạn tự tay viết những dòng code lập trình mạng đầu tiên.
Trong Bài 4, chúng ta sẽ bước sang Phần 2 thực chiến: Tự tay xây dựng một ứng dụng Chat Client - Server hoàn chỉnh bằng giao thức TCP!
Bạn đã sẵn sàng bước sang Bài 4 chưa?
All rights reserved