Chia sẻ kiến thức lập trình

TCP

Chuyển phát nhanh có đảm bảo!

Trong mô hình OSI 7 lớp, TCP chiếm 1 vị trí quan trọng trong lớp 4 bên cạnh UDP, SCTP và DCCP. Và ngày nay giao thức chúng ta sử dụng nhiều nhất cũng chính là TCP. Với lập trình viên, chúng ta thường xuyên sử dụng TCP thông qua 2 giao thức HTTP và Websocket ở tầng 7.

Vấn đề gửi nhận

Vậy tại sao TCP lại quan trọng và được sử dụng nhiều đến vậy? Có lẽ nhiều bạn ở đây đã từng gửi và nhận thư rồi nhỉ? Để gửi và nhận thư thì chúng ta cần biết được địa chỉ của người nhận và ghi rõ ở bì thư thì đơn vị chuyển phát họ mới gửi đến đúng người nhận được, và ngược lại, để nhận được thư thì người gửi cũng phải biết địa chỉ cũng chúng ta và ghi rõ ở bì thư.
Tất nhiên là chúng ta không thể tin tưởng tuyệt đối đơn vị chuyển phát nên chúng ta thường dán bì thư lại, và khi nhận thư nếu thấy bì thư đã bị xé hoặc thay đổi, nội dung bức thư đã bị tẩy xóa chúng ta có thể đoán đã có người thay đổi bức thư.
Trọng mạng internet của chúng ta các gói tin bản chất là các tín hiệu gửi qua các thiết bị vật lý, việc bị mất tín hiệu do đường truyền không ổn định, do các thiết bị vật lý bị hỏng hoặc có vấn đề. Khi một tín hiệu bị mất đi nó sẽ khiến cho toàn bộ gói tin bị thay đổi. Hãy ví dụ nhé, chúng ta cần gửi gói tin "HelloWorld" qua mạng, gói tin này có thể bị chia nhỏ thành 10 gói tin khác nhau: 'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'. Vậy điều gì xảy ra khi chúng ta bị mất 5 gói tin đầu? Tất nhiên rồi, chúng ta sẽ chỉ còn lại 5 gói tin và cái mà chúng ta nhận được chỉ còn la: World.

Mục tiêu ra đời

Để giải quyết các vấn đề kể trên, TCP đã ra đời với các mục tiêu:

  1. Đảm bảo gói tin phải đến được đích (thông qua cơ chế ACK), người nhận và người gửi phải biết được thông tin của nhau
  2. Đảm bảo người nhận có thể kiểm tra tính toàn vẹn của gói tin để biết được gói tin có bị lỗi không để yêu cầu gửi lại
  3. Đảm bảo thứ tự của các gói tin để thực hiện việc ghép nối gói tin lớn khi gửi nhận

Cái giá phải trả

Tuy nhiên để đảm bảo được các mục tiêu trên thì TCP cũng phải trả một chi phí không hề rẻ. Phần header của 1 gói tin TCP bao gồm:

  1. Source Port: 16 bits
  2. Destination Port: 16 bits
  3. Sequence Number: 32 bits
  4. Acknowledgment Number: 32 bits
  5. Data Offset: 4 bits
  6. Reserved: 6 bits
  7. Flags (9 bits): 9 bits
  8. Window: 16 bits
  9. Checksum: 16 bits
  10. Urgent Pointer: 16 bits
  11. Options (Variable 0–320 bits, in units of 32 bits)
  12. Padding: max 32-bit

Phức tạp nhưng phải thế!

Chúng ta có thể thấy phần header cực kì phức tạp và tốn nhiều bytes (tối thiểu 160 bits = 20 bytes), khi bạn chỉ có nhu cầu gửi 1 byte và bạn mất 20 bytes đi kèm, nó giống như việc bạn ăn 1 bán bún nhưng phải trả tiền 21 bát vậy.
Để có thể hiểu nội dung ở phần dưới trước tiên chúng ta cần hiểu khái niệm Initial Sequence Number (ISN). Hãy tưởng tượng thế này, A và B gửi thư trực tiếp cho nhau, rồi đến 1 ngày B phải đi du học, để gửi và nhận thư lúc này phải thông qua C, khổ cái là vì quá nhớ B nên A gửi liên tục thư cho B mà C thì quá lôi thôi nên khi đưa cho B thì nó đã trở thành 1 đống hỗn độn. Để sắp xếp các bức thư cho trình tự thì mỗi một đợt gửi thư A sẽ gửi cho B một con số và sau này 2 người cứ theo trình tự mà ghép nối lại các bức thư được gửi nhận, để tránh bị lẫn lộn thư của mỗi đợt trò chuyện các con số sinh ra cho mỗi đợt là ngẫu nhiên. Đó chính là ý tưởng cho ISN. ISN là một con số ngẫu nhiên được sinh ra cho mỗi đợt gửi nhận của 2 thiết bị thông qua giao thức TCP
Bây giờ hãy cùng xem nội dung của phần header có gì nhé:

  1. Source Port: 16 bits - Port của thiết bị gửi
  2. Destination Port: 16 bits - Port của thiết bị nhận
  3. Sequence Number: 32 bits - Được khởi tạo ban đầu bằng ISN, dùng để đảm dữ liệu được gửi nhận theo đúng thứ tự và đảm bảo khả năng gửi lại khi gói tin bị thất lạc
  4. Acknowledgment Number: 32 bits - Dùng để xác nhận rằng dữ liệu đã được nhận thành công
  5. Data Offset: 4 bits - Quy định kích thước của TCP header, header có độ dài tối thiểu 5 words và tối đa 15 words (2^4 - 1), mỗi word có độ dài là 4 vậy 1 header có độ dài tối thiểu 20 bytes và tối đa là 60 bytes
  6. Reserved: 6 bits: dùng cho tương lại, tạm thời bằng 0
  7. Flags (9 bits): 9 bits: Chứa các cờ
  8. Window size: 16 bits - Bạn hãy tưởng tượng như bạn đang chiếu phim vậy, mỗi khi gửi được 1 đoạn của gói tin cũng giống như chiếu được 1 đoạn phim, và window size chính là kích thước của đoạn tin hay chính là số ảnh trong 1 thước phim bạn chiếu qua trong 1 thời điểm
  9. Checksum: 16 bits - Dùng để kiểm tra xem có byte nào bị hỏng trong quá trình truyền tin không, hay nói cách khác là nội dung gói tin có bị thay đổi không
  10. Urgent Pointer: 16 bits - Nếu cờ URG bật thì giá trị trường này chính là số từ 16 bits mà số thứ tự gói tin (sequence number) cần dịch trái.
  11. Options (Variable 0–320 bits, in units of 32 bits) - Trường tùy chọn, có thể dùng trong tương lai
    Nó thực sự khó hiểu đúng không? Nhưng nó là thứ chúng ta cần phải hiểu nếu chúng ta muốn lập trình mạng và nó là kiến thức để chúng ta đưa ra khi phải lựa chọn một giao thức nào đó cho chương trình của mình.

Tham khảo:

  1. TCP
  2. TCP sequence acknowledgement numbers
  3. TCP sequence acknowledgement
  4. Understanding tcp sequence acknowledgment numbers
Share: