Giao thức Tcp: đóng mở kết nối, truyền dữ liệu

    0

    Trong bài học này chúng ta sẽ xem xét chi tiết hơn về giao thức Tcp để có thể hiểu rõ về cách thức lập trình với Tcp socket, bao gồm cấu trúc gói tin, thiết lập & hủy liên kết, cách truyền dữ liệu.

    Ở phần thực hành chúng ta đã thực hiện một chương trình client/server cơ bản sử dụng Tcp socket. Do Tcp là một giao thức rất phức tạp, trước khi đi vào phân tích chi tiết kỹ thuật lập trình Tcp socket, chúng ta sẽ xem xét các vấn đề chính của giao thức Tcp.

    Quay trở lại Hướng dẫn tự học lập trình socket Tcp/Ip.

    Cấu trúc gói tin của giao thức Tcp

    Đóng gói dữ liệu

    Tương tự như Udp, Tcp cũng chỉ vận chuyển các chuỗi byte (mà ứng dụng tạo ra) mà không quan tâm tới ý nghĩa của chúng.

    Dữ liệu của ứng dụng sau khi chuyển qua socket tới tầng giao vận sẽ được giao thức TCP tách thành từng phần. Đối với mỗi phần dữ liệu này, TCP sẽ bổ sung thêm các thông tin điều khiển vào trước phần dữ liệu để tạo thành một đơn vị dữ liệu của tầng giao vận, gọi là TCP segment.

    Phần thông tin điều khiển mà TCP thêm vào trước khối dữ liệu ứng dụng gọi là TCP header. Phần dữ liệu ứng dụng lưu trong TCP segment được gọi là payload. TCP segment sau đó sẽ tiếp tục được chuyển xuống tầng mạng và tiến hành đóng với với giao thức IP để tạo thành một đơn vị dữ liệu của tầng mạng, gọi là IP datagram (hoặc IP package).

    Tại tầng liên kết IP package lại được đóng gói một lần nữa thành Ethernet frame trước khi đưa lên đường truyền vật lý. 

    Tcp header

    Cấu trúc của TCP header được trình bày trong sơ đồ dưới đây:

    Cấu trúc TCP header
    Cấu trúc TCP header

    Xem lại bài này để hiểu cách biểu diễn mảng byte của header

    Ý nghĩa các trường như sau:

    • Source port (16 bit): số cổng của tiến trình gửi.
    • Destination port (16 bit): số cổng của của tiến trình nhận.
    • Sequence number (32 bit): số thứ tự. Giá trị và ý nghĩa của số thứ tự phụ thuộc vào giá trị của bit SYN.
    • Các trường flag (6 trường, mỗi trường 1 bit):
      • Bit ACK dùng để xác nhận tính chính xác của giá trị trường Acknowledgement.
      • Bit RST, SYN, FIN dùng để thiết lập và hủy bỏ kết nối.
      • Bit PSH chỉ định máy nhận phải chuyển dữ liệu lên tầng trên ngay lập tức.
      • Bit URG chỉ định rằng có vùng dữ liệu được đánh dấu là “urgent” (dữ liệu khẩn). Nếu URG=1, trường Urgent pointer (16 bit) sẽ chứa vị trí của byte cuối cùng của dữ liệu khẩn; TCP phải thông báo về sự tồn tại của dữ liệu khẩn cho máy nhận, đồng thời chuyển cho máy nhận một con trỏ tới cuối của vùng dữ liệu khẩn. Trong thực tế, hai trường PSH và URG không được sử dụng.
    • Checksum (16 bit): sử dụng để kiểm tra lỗi.
    • Window size (16 bit): kích thước cửa sổ dùng trong kiểm soát luồng.
    • Reserved (3 bit): luôn chứa giá trị 000, để dành sử dụng trong tương lai.
    • Data offset (4 bit), còn gọi là Header length: kích thước của TCP header. Kích thước của TCP header có thể thay đổi do sự tồn tại của trường Options. Tuy nhiên, trường Options này thường để trống, và do đó, kích thước của TCP header thường là 20 byte.
    • Acknowledgement number (32 bit): số báo nhận. Trường số thứ tự và số báo nhận được sử dụng để đảm bảo dịch vụ truyền dữ liệu tin cậy.
    • Options (độ dài thay đổi): được sử dụng khi hai máy tham gia truyền thông thỏa thuận về kích thước tối đa của segment (TA: maximum segment size, MSS) hoặc hệ số tỉ lệ của cửa sổ trượt (dùng cho các mạng tốc độ cao).

    Quy trình hoạt động của giao thức Tcp

    Quy trình hoạt động của Tcp chia làm 3 giai đoạn: Thiết lập liên kết, Truyền dữ liệu và Đóng liên kết.

    Thiết lập liên kết Tcp

    Khi một tiến trình muốn tiến hành truyền thông với với một tiến trình khác qua mạng sử dụng giao thức TCP, nó phải thông báo cho tầng giao vận để khởi tạo một liên kết TCP. Trong quá trình này, tiến trình khởi tạo liên kết được gọi là tiến trình khách, tiến trình còn lại tiếp nhận liên kết TCP được gọi là tiến trình chủ.

    Bắt tay ba bước

    Quá trình thiết lập liên kết TCP giữa hai tiến trình được thực hiện trong ba bước và thường được gọi là quá trình bắt tay ba bước (three-way handshake).

    Bước 1. Tiến trình khách gửi một TCP segment không chứa dữ liệu tới tiến trình chủ, trong đó, bit SYN = 1. Tiến trình khách sẽ chọn một giá trị ngẫu nhiên cho trường Sequence (để tránh tấn công loại SYN). Segment loại này thường được gọi là SYN segment.

    Bước 2. Khi tiến trình chủ nhận được SYN segment, nó sẽ bố trí bộ nhớ cho TCP buffer và các biến trạng thái cho liên kết TCP. Tiến trình chủ sau đó sẽ gửi một segment trả lời cho tiến trình khách, trong segment này: bit SYN = 1; số báo nhận (ACK number) = Sequence của SYN segment (nhận từ tiến trình khách) + 1; số thứ tự Sequence được lựa chọn ngẫu nhiên. Segment trả lời này thường được gọi là SYNACK segment.  

    Bước 3. Khi nhận được SYNACK segment, tiến trình khách cũng thiết lập bộ nhớ đệm và các biến trạng thái cho liên kết TCP, sau đó gửi lại cho tiến trình chủ một segment, trong đó, trường số báo nhận ACK = số thứ tự Sequence của server + 1, SYN = 0, trường số thứ tự Sequence tăng thêm 1 đơn vị.

    Quá trình bắt tay ba bước của Tcp
    Quá trình bắt tay ba bước của Tcp

    Sau 3 bước này, liên kết TCP giữa hai tiến trình đã được thiết lập.

    Đặc điểm của liên kết Tcp

    Liên kết TCP là loại liên kết song công (TA: full-duplex). Tức là, một khi thiết lập được liên kết giữa tiến trình A và tiến trình B, dữ liệu tầng ứng dụng có thể đồng thời truyền từ A tới B và từ B tới A.

    Liên kết TCP thuộc loại liên kết điểm-điểm (TA: point-to-point) giữa duy nhất một tiến trình gửi và một tiến trình nhận. Trong TCP không tồn tại loại truyền thông kiểu quảng bá (TA: multicasting) giữa một tiến trình gửi với nhiều tiến trình nhận.

    Truyền dữ liệu

    Khi đã hình thành liên kết TCP, hai tiến trình tham gia liên kết có thể truyền dữ liệu cho nhau. Khi một tiến trình chuyển một chuỗi byte qua socket tới tầng giao vận, dữ liệu đó sẽ hoàn toàn do TCP trên máy đó quản lý và chịu trách nhiệm.

    Truyền dữ liệu qua liên kết Tcp
    Truyền dữ liệu qua liên kết Tcp: song công, segment, các buffer

    TCP có thể coi như một hệ thống con của hệ điều hành chịu trách nhiệm nhận dữ liệu từ ứng dụng cục bộ cũng như nhận dữ liệu từ máy ở xa.

    Tcp buffer

    TCP không lập tức đóng gói dữ liệu và chuyển lên mạng. Thay vào đó, Tcp chuyển dữ liệu tới một bộ nhớ đệm (buffer) được hình thành trong quá trình bắt tay ba bước. Theo thời gian, TCP sẽ lấy dữ liệu (dữ liệu của ứng dụng) từ bộ nhớ đệm, đóng gói thành segment, và chuyển lên đường truyền.

    Trong khoảng thời gian chờ ở bộ nhớ đệm, ứng dụng có thể gửi thêm dữ liệu và dữ liệu này sẽ tiếp tục được bổ sung vào bộ nhớ đệm. Tương tự, TCP trên máy đích cũng sử dụng một bộ nhớ đệm cục bộ của riêng mình để lưu dữ liệu nhận được cho đến khi nó nhận được đầy đủ tất cả các gói tin theo đúng thứ tự. Sau đó, dữ liệu này mới được chuyển lên cho ứng dụng.

    Tcp segment

    Đơn vị dữ liệu của Tcp được gọi là segment. Kích thước tối đa của segment (maximum segment size, MSS) được thiết lập tự động bằng cách xác định kích thước tối đa của frame dữ liệu của tầng liên kết. Việc thiết lập MSS như vậy đảm bảo cho TCP segment có thể nằm vừa khít trong một frame với kích thước đủ lớn để có hiệu suất gửi dữ liệu cao nhất.

    Khi TCP gửi đi dữ liệu kích thước lớn (ví dụ, một file ảnh lớn trong một trang web), dữ liệu này sẽ được cắt thành từng phần có kích thước bằng MSS (trừ mảnh cuối cùng có thể có kích thước nhỏ hơn).

    Ngược lại, các ứng dụng tương tác thường dùng các khối dữ liệu có kích thước nhỏ hơn MSS. Ví dụ, chương trình Telnet thường gửi đi dữ liệu có kích thước đúng 1 byte, do đó kích thước TCP segment dùng với Telnet thường chỉ có 21 byte.

    Acknowledgement

    Mỗi khi Tcp trên máy nguồn gửi đi một segment, nó sẽ chờ nhận được một gói tin phản hồi (ACK) từ máy đối tác thông báo về tình trạng của segment vừa nhận. Chỉ khi có ACK xác nhận đạt yêu cầu, Tcp trên máy nguồn mới tiếp tục gửi đi segment tiếp theo.

    Do những đặc điểm trên, khi tiến trình gửi dữ liệu đi (dưới dạng các thông điệp thuộc tầng ứng dụng), TCP đảm bảo việc chuyển được toàn bộ dữ liệu tới máy đích theo đúng thứ tự, không mất mát và không lỗi.

    Nhìn từ khía cạnh ứng dụng, liên kết và truyền dữ liệu qua Tcp giống như một luồng byte liên tục “chảy” từ buffer của máy nguồn tới buffer của máy đích. Khi tới buffer của máy đích, dữ liệu sẽ chờ được lấy vào chương trình và xử lý. Vì là một dòng byte liên tục, TCP không đảm bảo duy trì “ranh giới” giữa các thông điệp. Việc phân tách nội dung thông điệp tầng ứng dụng thuộc trách nhiệm của chương trình ứng dụng.

    Đóng liên kết

    Cả hai tiến trình tham gia vào liên kết TCP đều có thể yêu cầu đóng liên kết.

    Khi một trong hai tiến trình muốn kết thúc một liên kết, nó sẽ gửi đi một segment không chứa dữ liệu, trong đó bit FIN = 1.

    Khi tiến trình còn lại nhận được segment này, nó sẽ gửi lại một ACK segment. Tiếp theo tiến trình này sẽ gửi tiếp một segment, trong đó bit FIN = 1.

    Cuối cùng, tiến trình muốn kết thúc liên kết sẽ gửi một ACK segment. Ngay sau đó, bộ nhớ đệm và các biến trạng thái liên quan tời liên kết sẽ được giải phóng và liên kết được ngắt.

    Bình luận

    avatar
      Đăng ký theo dõi  
    Thông báo về