TCP – Giới thiệu về Thiết lập Kết nối

10 min read

tcp

Transmission Control Protocol (TCP) cung cấp một dịch vụ transport layer dạng byte-stream,  connection-oriented và đáng tin cậy. Việc triển khai của nó cũng khá thú vị.

Trong bài viết này, chúng ta sẽ khám phá cách thiết lập kết nối TCP hoạt động như thế nào, cách nó đảm bảo độ tin cậy bằng cách duy trì trạng thái kết nối và liệu nó có phù hợp với mọi trường hợp sử dụng hay không.

Nhưng trước khi đi vào chi tiết của quá trình bắt tay, hãy cùng xem qua TCP.

TCP là gì?

Một kết nối TCP được định nghĩa là một 4-tuple bao gồm hai địa chỉ IP và hai port numbers. Mỗi cặp địa chỉ IP – port đại diện cho một điểm cuối.

Điều này có nghĩa là một máy chủ đơn lẻ có thể kết nối với nhiều máy khách nếu địa chỉ IP và/hoặc port của chúng là duy nhất.

TCP phù hợp ở đâu? Giao thức điều khiển truyền tải (TCP) là một trong những giao thức tầng vận chuyển có sẵn và nó được sử dụng rộng rãi vì nhiều lý do chính đáng.

Để hiểu tại sao nó lại cần thiết, hãy xem qua mô hình ngăn xếp giao thức trong mô hình TCP/IP:

tcp

HTTP request đến từ application layer (ví dụ: trình duyệt của bạn) đi qua tất cả các layer được gửi qua internet. Internet Layer xử lý việc gửi ra các mảnh dữ liệu nhỏ, còn được gọi là IP datagrams. Các datagram này hoạt động như một phong bì cho TCP segments và nhiệm vụ của tầng IP là gửi chúng qua internet.

Vì IP Layer không nhận thức được kết nối TCP, nên hai gói tin tương ứng với cùng một kết nối thường được gửi qua các tuyến khác nhau. Điều này làm cho việc truyền dữ liệu qua internet không đáng tin cậy và gây ra nhiều vấn đề như gói tin trùng lặp, gói tin sai thứ tự, mất gói tin, v.v.

TCP cung cấp các biện pháp xử lý cho tất cả các tình huống này và đảm bảo việc truyền tải gói tin không mất mát, đúng thứ tự tại đầu nhận.

TCP Header & IP datagram

TCP Segments mang tất cả các thông tin meta về kết nối trong header. TCP header cơ bản là 20 byte (không bao gồm các tùy chọn), điều này có nghĩa là 20 byte dữ liệu dư thừa cho bất kỳ gói tin nào khi truyền tải. Hãy hiểu những gì cấu thành một TCP header:

  1. Source and Destination port (Cổng nguồn và Cổng đích).
  2. Sequence Number (Số thứ tự): Đây là số nhận diện byte đầu tiên trong phân đoạn được gửi tới TCP nhận.
  3. Acknowledgement Number (Số xác nhận): Chứa Số thứ tự tiếp theo mà bên gửi xác nhận dự kiến sẽ nhận được, tức là:
    • Acknowledgement Number = Sequence Number + 1
  4. Window Size: Đây là số byte mà TCP nhận sẵn sàng nhận. Nó là một trường 16 bit, giới hạn Window Size ở mức 65.535 byte. Chúng ta sử dụng Window Scaling để khắc phục nút thắt này.
  5. TCP Checksum (Kiểm tra TCP): Điều này bắt buộc được gửi bởi TCP bên gửi và được xác minh bởi bên nhận để phát hiện sự hỏng dữ liệu.
  6. Urgent Pointer (Con trỏ khẩn cấp): Cơ chế này trong TCP được sử dụng để gửi một số dữ liệu cụ thể và khẩn cấp đến đầu kia. Nó chỉ có hiệu lực nếu trường URG được thiết lập.
  7. Other Bit Fields (Các trường bit khác): Chủ yếu hai trường được sử dụng trong quá trình thiết lập kết nối:
    • SYN: Bit này được bật trong phân đoạn đầu tiên, ở giai đoạn bắt đầu thiết lập kết nối.
    • ACK: Được sử dụng khi cần gửi xác nhận. Luôn bật ngoại trừ gói tin đầu tiên và cuối cùng (giai đoạn kết thúc kết nối).

Tất cả thông tin về kết nối này được lưu trữ trong TCP header. Kết hợp header này với dữ liệu ứng dụng tạo ra TCP Segment:

tcp-segment

Nhưng đến giai đoạn này, chúng ta chỉ mới biết về các cổng nguồn và cổng đích. Chúng ta cũng cần các địa chỉ IP nguồn và đích để nhận diện duy nhất một kết nối TCP. Điều này xảy ra ở tầng tiếp theo (tức là tầng IP) trong quá trình truyền tải.

Tầng IP chỉ đơn giản là thêm header của nó lên trên phân đoạn TCP mà nó nhận được, tạo thành một “IP Datagram”. Các headers này lần lượt được gỡ bỏ tại đầu nhận, theo thứ tự ngược lại.

Vì vậy, tầng TCP và tầng IP cùng nhau tạo thành một kết nối TCP duy nhất. Và chúng ta có “Bộ Giao thức TCP/IP” (TCP/IP Protocol Suite).

Thiết lập

Thiết lập kết nối được bắt đầu bởi một bên chủ động mở (thường là máy khách) muốn kết nối với một bên thụ động mở (thường là máy chủ) và tổng cộng ba phân đoạn TCP được truyền trong quá trình này. Mục tiêu của quá trình này là để mỗi đầu của kết nối biết rằng một kết nối đang bắt đầu, chia sẻ một số cấu hình quan trọng (còn gọi là tùy chọn TCP) và trao đổi Số thứ tự ban đầu (ISN).

Bên chủ động mở quyết định Số thứ tự ban đầu (ISN) khi khởi tạo kết nối. Tính khó đoán của ISN rất quan trọng đối với bảo mật của kết nối. Một kẻ ngoài cuộc có thể lừa bên nhận (hoặc bên thụ động mở) và giả mạo là người gửi thực sự nếu họ có thể dự đoán được ISN.

[Segment 1]: The client gửi 1 SYN segment

Phân đoạn TCP đầu tiên được gửi bởi bên chủ động mở (hoặc máy khách) chứa các thông tin sau:

  • Cổng của máy chủ được lưu trữ trong Cổng Đích (Destination Port).
  • Bit SYN được thiết lập trong các Cờ TCP (TCP Flags).
  • ISN của máy khách được lưu trữ trong Số Thứ Tự (Sequence Number).
  • Một số tùy chọn cấu hình được lưu trữ trong Tùy Chọn TCP (TCP options) (chúng ta sẽ giải quyết chúng ở phần tiếp theo).

[Segment 2]: Máy chủ phản hồi bằng phân đoạn SYN-ACK

Máy chủ gửi phân đoạn SYN của riêng mình. Nó cũng xác nhận phân đoạn nhận được từ máy khách. Nó gửi một phân đoạn với:

  • Bit SYN được bật
  • Số Thứ Tự = ISN(máy chủ)
  • Bit ACK được bật (để xác nhận phân đoạn nhận được từ đồng nghiệp)
  • Số Xác Nhận = ISN(máy khách) + 1

[Segment 3]: Máy khách gửi phân đoạn ACK cuối cùng

Cuối cùng, máy khách xác nhận phân đoạn SYN nhận được từ máy chủ bằng một ACK. Cụ thể:

  • Nó thiết lập bit ACK để xác nhận phân đoạn SYN của máy chủ
  • Số Thứ Tự = ISN(máy khách) + 1
  • Số Xác Nhận = ISN(máy chủ) + 1 Nếu phân đoạn SYN bị mất, nó sẽ được gửi lại cho đến khi một ACK cho nó được nhận.

TCP Options

Có một số cài đặt cấu hình bổ sung giúp trong việc truyền dữ liệu một cách hiệu quả trong một kết nối TCP. Một số tùy chọn này chỉ có thể được thiết lập một lần trong quá trình thiết lập kết nối trong khi các tùy chọn khác có thể được sử dụng bất kỳ lúc nào trong quá trình tồn tại của kết nối.

Hãy xem một số tùy chọn TCP phổ biến nhất

Maximum Segment Size  (MSS)
Đây là phân đoạn lớn nhất mà TCP sẵn sàng nhận từ thiết bị ngang hàng của nó, là kích thước lớn nhất mà thiết bị ngang hàng của nó sẽ sử dụng khi gửi.

Điều quan trọng cần lưu ý ở đây là MSS chỉ tính dữ liệu ứng dụng chứ không tính các TCP & IP Header. Mặt khác, Đơn vị có thể chuyển tối đa (MTU) xem xét toàn bộ gói bao gồm các TCP & IP Header.

Kích thước của MSS và MTU có thể được cấu hình nhưng phải nằm dưới khả năng kích thước tối đa của Ethernet Frame mà chứa những gói tin đó. Kích thước MTU có thể được đặt lớn hơn khả năng của Frame, nhưng sau đó gói tin sẽ cần phải trải qua việc phân mảnh để được gửi đi.

Window Scaling

Window Size cho biết cho đồng nghiệp trong kết nối biết bao nhiêu bộ nhận đã được phân bổ hoặc còn lại cho kết nối cụ thể đó. Tùy chọn này được thiết lập trong giai đoạn thiết lập kết nối và không thể thay đổi trong suốt thời gian tồn tại của kết nối.

Window Size trong TCP header là 16 bit, làm cho giá trị tối đa chỉ có thể là 65536 byte (2^16) mà thôi. Trong trường hợp mạng có độ trễ cao, có một Window Size của 64KB có thể làm cho các vòng đi lại lớn hơn và Thời Gian Đi lại (RTT) lâu hơn.

Window Scaling TCP option là một trường 14 bit, nó dịch trái giá trị Window Size làm cho nó lớn hơn đáng kể với giá trị tối đa lên đến 1GB (65535 byte * 2^14). Điều này rất hữu ích khi làm việc trong tình huống có băng thông lớn và độ trễ cao.

Hãy hiểu rõ hơn với hình minh họa ở đây:

Sau khi Window Scaling được set, bên gửi có thể gửi một lượng dữ liệu gấp đôi và làm giảm thời gian rảnh rỗi. Do đó, sử dụng hiệu quả hơn.

Tương tự, việc sử dụng hệ số window scaling lớn hơn sẽ tăng thêm kích thước window hiệu quả. Càng nhiều windows, TCP gửi dữ liệu có thể gửi mà không nhận bất kỳ xác nhận nào.

Xác nhận Lựa chọn (SACK)

Các gói tin gửi qua mạng thường bị mất dẫn đến những bước nhảy đột ngột trong các số xác nhận và khiến dãy byte không liên tục. Điều này tạo ra “lỗ hổng” trong dữ liệu nhận được và TCP gửi không biết gói tin nào cần được gửi lại.

Với SACK được hỗ trợ ở cả hai đầu (được thỏa thuận trong quá trình thiết lập kết nối), bên nhận có thể truyền tải các gói tin nó nhận được sau khoảng trống. Hai trường giúp xác định các gói tin bị thiếu:

  • Số Xác Nhận được đặt thành vị trí gói tin cuối cùng nó nhận trước khoảng trống.
  • Một khối SACK trong các tùy chọn TCP chứa khối dữ liệu nó nhận được sau khoảng trống.

TCP gửi lấy sự khác biệt vị trí giữa gói tin đầu tiên sau khoảng trống và gói tin cuối cùng trước khoảng trống. Điều này làm cho việc nhận dạng khối dữ liệu cần gửi lại trở nên dễ dàng hơn cho TCP gửi.

Ví dụ, nếu một TCP nhận xác nhận (trùng lặp) là 1000 và khối SACK chứa một dãy từ 1100-1500, rõ ràng là TCP gửi cần gửi lại chỉ các gói tin từ 1000 đến 1100.

NOP Điều này giúp TCP đệm các trường để đến một bội số của 4 byte khi dữ liệu thực tế không tuân theo các ràng buộc kích thước.

EOL Nó chỉ ra cuối của danh sách các tùy chọn và cho thấy không cần thiết phải xử lý thêm danh sách tùy chọn.

Xem thêm nhiều bài viết hơn tại đây

Avatar photo

Clean Code: Nguyên tắc viết hàm trong lập trình…

Trong quá trình phát triển phần mềm, việc viết mã nguồn dễ đọc, dễ hiểu là yếu tố then chốt để đảm bảo code...
Avatar photo Dat Tran Thanh
3 min read

Leave a Reply

Your email address will not be published. Required fields are marked *