UDP vẫn tốt hơn TCP cho các trò chơi thời gian thực nặng dữ liệu?


71

Tôi biết rằng UDP thường được khuyên dùng cho các trò chơi nhiều người chơi trong thời gian thực với mức sử dụng dữ liệu cao.

Hầu hết các bài viết đều có tuổi đời và vì ~ 80% tất cả dữ liệu được truyền trên internet là TCP, rất nhiều tối ưu hóa phải được thực hiện cho TCP.

Điều này khiến tôi tự hỏi: liệu UDP vẫn vượt trội về tốc độ và độ trễ? Tối ưu hóa TCP gần đây có thể làm cho TCP hoạt động tốt hơn UDP không?


25
Với UDP, không có gì đảm bảo rằng các gói của bạn sẽ được nhận hoặc thậm chí được đặt hàng, chính điều đó làm cho UDP nhanh hơn TCP.
nathan

4
@KaareZ bạn có ý nghĩa gì để thực hiện nhanh hơn?
nathan

2
@nathan Điều đó dễ dàng phát triển ứng dụng của bạn với TCP hơn UDP. Tôi muốn biết rằng tất cả các tối ưu hóa TCP đã làm cho TCP trở thành một lựa chọn tốt hơn về mặt hiệu suất.
KaareZ

3
@KaareZ Tôi không phải là chuyên gia nhưng hãy nghĩ về nó. Làm thế nào TCP có thể tốt hơn về mặt hiệu suất và vẫn là một giao thức đáng tin cậy? Bạn không thể có mọi thứ. TCP được tạo ra để đảm bảo độ tin cậy. Câu hỏi thực sự là tại sao bạn muốn sử dụng TCP trong trò chơi của mình?
nathan

7
UDP tốt hơn TCP nếu và chỉ khi bạn có thể (= lập trình viên mạng cấp thấp có kinh nghiệm) triển khai lại chỉ các tính năng TCP bạn cần bên trong nó một cách hiệu quả. Giảm các tính năng TCP không cần thiết cho hiệu suất.
wonderra

Câu trả lời:


119

Không, UDP vẫn vượt trội về độ trễ hiệu năng và sẽ luôn nhanh hơn, vì triết lý của 2 giao thức - giả sử dữ liệu truyền thông của bạn được thiết kế với UDP hoặc bất kỳ giao tiếp mất mát nào khác.

TCP tạo ra một sự trừu tượng trong đó tất cả các gói mạng đến và chúng đến theo thứ tự chính xác mà chúng được gửi. Để thực hiện một sự trừu tượng như vậy trên một kênh bị mất, nó phải thực hiện truyền lại và hết thời gian, tiêu tốn thời gian. Nếu bạn gửi 2 bản cập nhật trên TCP và một gói của bản cập nhật đầu tiên bị mất, bạn sẽ không thấy bản cập nhật thứ hai cho đến khi:

  1. Mất bản cập nhật đầu tiên được phát hiện.
  2. Yêu cầu truyền lại bản cập nhật đầu tiên.
  3. việc truyền lại đã đến và được xử lý.

Không quan trọng việc này được thực hiện nhanh như thế nào trong TCP, bởi vì với UDP, bạn chỉ cần loại bỏ bản cập nhật đầu tiên và sử dụng bản cập nhật thứ hai, mới hơn, ngay bây giờ. Không giống như TCP, UDP không đảm bảo rằng tất cả các gói đến và nó không đảm bảo rằng chúng đến theo thứ tự.

Điều này đòi hỏi bạn phải gửi đúng loại dữ liệu và thiết kế giao tiếp của bạn theo cách mà việc mất dữ liệu được chấp nhận.

Nếu bạn có dữ liệu mà mọi gói phải đến và các gói phải được xử lý bởi trò chơi của bạn theo thứ tự chúng được gửi, thì UDP sẽ không nhanh hơn. Trong thực tế, việc sử dụng UDP trong trường hợp này có thể sẽ chậm hơn vì bạn đang xây dựng lại TCP và triển khai nó bằng UDP trong trường hợp đó bạn cũng có thể sử dụng TCP.

EDIT - Thêm một số thông tin bổ sung để kết hợp / giải quyết một số ý kiến:

Thông thường, tốc độ mất gói trên Ethernet rất thấp, nhưng nó sẽ trở nên cao hơn nhiều khi có liên quan đến WiFi hoặc nếu người dùng đang tiến hành tải lên / tải xuống. Giả sử chúng ta có một gói mất hoàn toàn thống nhất là 0,01% (một chiều, không phải khứ hồi). Trên một game bắn súng góc nhìn người thứ nhất, khách hàng nên gửi thông tin cập nhật bất cứ khi nào có chuyện gì xảy ra, chẳng hạn như khi con trỏ chuột xoay người chơi, điều này xảy ra khoảng 20 lần mỗi giây. Họ cũng có thể gửi các bản cập nhật trên mỗi khung hoặc trong một khoảng thời gian cố định, sẽ là 60-120 cập nhật mỗi giây. Vì các bản cập nhật này được gửi vào các thời điểm khác nhau, nên chúng sẽ / nên được gửi trong một gói cho mỗi bản cập nhật. Trên trò chơi 16 người chơi, tất cả 16 người chơi gửi 20-120 gói này mỗi giây đến máy chủ, dẫn đến tổng số 320-1920 gói mỗi giây. Với tỷ lệ mất gói là 0,01%, chúng tôi hy vọng sẽ mất gói sau mỗi 5,2-31,25 giây.

Trên mỗi gói chúng tôi nhận được sau gói bị mất, chúng tôi sẽ gửi DupAck và sau DupAck thứ 3, người gửi sẽ gửi lại gói bị mất . Vì vậy, thời gian TCP yêu cầu để bắt đầu truyền lại là 3 gói, cộng với thời gian để DupAck cuối cùng đến người gửi. Sau đó, chúng tôi cần đợi truyền lại đến, vì vậy tổng cộng chúng tôi chờ 3 gói + 1 độ trễ khứ hồi. Độ trễ khứ hồi thường là 0-1 ms trên mạng cục bộ và 50-200 ms trên internet. 3 gói thường sẽ đến trong 25 ms nếu chúng tôi gửi 120 gói mỗi giây và trong 150ms nếu chúng tôi gửi 20 gói mỗi giây.

Ngược lại, với UDP, chúng tôi phục hồi từ gói bị mất ngay khi nhận được gói tiếp theo, vì vậy chúng tôi mất 8,3 ms nếu chúng tôi gửi 120 gói mỗi giây và 50 ms nếu chúng tôi gửi 20 gói mỗi giây.

Với TCP, mọi thứ trở nên rắc rối hơn nếu chúng ta cũng cần xem xét Nagle (nếu nhà phát triển quên tắt gửi kết hợp hoặc không thể vô hiệu hóa ACK bị trì hoãn ), tránh tắc nghẽn mạng hoặc nếu mất gói là đủ để chúng ta phải tính toán nhiều mất gói (bao gồm mất Ack và DupAck). Với UDP, chúng tôi có thể dễ dàng viết mã nhanh hơn vì chúng tôi hoàn toàn không quan tâm đến việc trở thành một công dân mạng tốt như TCP.


Lưu ý: UDP có thể phát sóng mạng cục bộ (lợi thế có thể) và vì Vista yêu cầu quản trị viên chạy máy chủ / phát trên UDP (bất lợi) (UAC / tường lửa có xu hướng không thông báo hành động của người dùng là bắt buộc).
PTwr

7
"Nếu bạn gửi 2 bản cập nhật trên TCP và một gói của bản cập nhật đầu tiên bị mất" Đúng, nhưng cơ hội cho điều đó xảy ra là gì? Theo pingman : "Bất cứ điều gì mất hơn 2% gói trong một khoảng thời gian là một chỉ báo mạnh mẽ cho các vấn đề."
mucaho

30
@Peter bạn đang quên rằng trong TCP, mọi gói tin bị mất sẽ ngăn chặn mọi gói tiếp theo. Với ping 100ms, nó có thể dễ dàng là 300-500ms trước khi gói đó được truyền lại và nhận, do đó, 6-10 gói bị đình trệ cứ sau 33 giây. Điều đó chắc chắn sẽ được chú ý trong một FPS giống như trận động đất.
BlueRaja - Daniel Pflughoeft

12
Trên nhiều triển khai TCP, thời gian chờ đầu tiên sau khi ack bị mất sẽ mất toàn bộ giây. Đó là một thời gian dài . Nếu các gói nhỏ, UDP có thể dễ dàng chuyển qua một hoặc hai lần truyền bị nhỡ bằng cách chỉ cần mỗi gói bao gồm dữ liệu từ hai bản cập nhật gần nhất để ứng dụng có được dữ liệu cần thiết trước khi người gửi hoặc người nhận có thể biết gói đầu tiên bị mất.
supercat

23
Với một game như Quake, việc mất gói đầu tiên là không liên quan. Trong FAR ít hơn thời gian, bạn sẽ phải phát hiện mất và truyền lại gói đầu tiên, bạn đã gửi một gói thứ hai khiến gói thứ nhất trở nên lỗi thời. Đây là lý do tương tự như nhiều ứng dụng thoại và video thời gian thực cũng sử dụng UDP. Nếu một gói bị bỏ, bạn sẽ chỉ mất 0,02 giây âm thanh hơn là trì hoãn toàn bộ luồng trong một giây hoặc nhiều hơn. Điều tương tự cũng thường đúng với các trò chơi thời gian thực, vì bạn muốn biết một đối tượng hiện đang ở đâu chứ không phải 1,5 giây trước.
thiệu lại vào

19

Chúng tôi đồng ý rằng cả TCP và UDP đều là các giao thức được xây dựng trên IP , phải không? IP chỉ định cách gửi tin nhắn qua internet, nhưng không có gì liên quan đến cấu trúc, định dạng tin nhắn. Ở đây có giao thức TCP và UDP. Họ sử dụng các thuộc tính IP, nhưng để lập trình viên tập trung vào trao đổi tin nhắn mà không phải lo lắng về các lớp truyền thông mạng thấp hơn. Và điều đó thật tuyệt vời, bởi vì xử lý trực tiếp các tín hiệu tương tự trong dây dẫn sẽ gây đau đớn.

  • TCP cung cấp một tập hợp các chức năng để gửi và nhận tin nhắn. Nó chia dữ liệu của chúng tôi thành các gói nhỏ cho chính chúng tôi và gửi chúng qua mạng. Tất cả những gì chúng tôi được yêu cầu là một cổng để sử dụng cho ổ cắm mạng và thông điệp thực tế chúng tôi muốn gửi. Ngoài ra, nó đáng tin cậy, có nghĩa là nếu một số gói bị mất dọc theo mạng mà chúng được phát hiện, sau đó được gửi lại, hãy cẩn thận gửi chúng theo đúng thứ tự chúng sẽ đến.

  • Mặt khác, UDP là một giao thức hướng đến kiểm soát người dùng. Khi sử dụng UDP để gửi datagram của chúng tôi , chúng tôi không thể chắc chắn liệu datagram có đến đích hay không (và chúng tôi có nghĩa là sự chắc chắn về mặt toán học ở đây: khi chúng tôi gửi một gói có thể sẽ đến, nhưng chúng tôi không thể chắc chắn tại 100%). Ngoài ra, khi một gói bị mất, nó sẽ không được phát hiện hay gửi lại.

Tại thời điểm này, TCP sẽ giống như giải pháp lý tưởng cho tất cả các vấn đề của chúng tôi. Nó đáng tin cậy, rất nhanh, nó giải quyết độ trễ kết nối cho chúng tôi bằng cách theo dõi những gói nào đã đến và những gói nào chúng tôi vẫn cần gửi.

NHƯNG , nhìn xa hơn. Ưu điểm duy nhất mà UDP mang lại cho chúng ta là tốc độ và đó là điều chúng ta thực sự muốn. Một gói UDP chỉ được chế tạo, kiểm tra tổng hợp và gửi mà không có bất kỳ điều khiển cụ thể nào, bởi vì đó là cách giao thức UDP hoạt động. Một gói TCP phải được chế tạo, dán nhãn, kiểm tra tổng hợp và khi nó đến, một ACK được gửi lại để nói với người gửi "gói x ở đây, tiếp tục" và khi tín hiệu này không được gửi thì có nghĩa là gói x đó phải được gửi một lần nữa

Tôi biết rằng UDP thường được khuyên dùng cho các trò chơi nhiều người chơi trong thời gian thực với mức sử dụng dữ liệu cao.

Có, nhưng không chỉ. UDP chủ yếu được ưa thích hơn TCP chủ yếu vì tốc độ cao của nó là ý tưởng để xử lý việc gửi và quản lý dữ liệu cao. Điều này xảy ra khi, giả sử trò chơi điện tử đó chạy trên bước khóa xác định (những gì xảy ra trên máy chủ được sao chép giống hệt nhau trên bất kỳ máy khách nào độc lập với độ trễ mạng), một gói cập nhật bị mất và không bao giờ đến đích. TCP sẽ gửi lại gói như vậy và các gói sau bị loại bỏ vì không đến theo thứ tự và sau đó được gửi lại sau gói bị mất. UDP khoan dung hơn nhiều trong kịch bản này: nó sẽ không quan tâm đến gói này, bởi vì các bản cập nhật mới hơn đang đến. Bản cập nhật bị mất không được hiển thị, thay vào đó, vật lý trò chơi được nội suy theo phương pháp tích hợp được sử dụng và bản cập nhật mới nhất nhận được.

TCP gây ra hiện tượng giật khi độ trễ đủ cao, UDP không:

<video style="min-width: 100% height: auto" autoplay="" preload="auto" loop="true"><source src="https://gafferongames.com/videos/deterministic_lockstep_tcp_250ms_5pc.mp4" type="video/mp4"><source src="http://173.255.195.190/cubes_deterministic_lockstep_tcp_250ms_5pc.webm" type="video/webm">Your browser does not support the video tag.</video>

Điều này khiến tôi tự hỏi liệu UDP vẫn vượt trội về tốc độ và độ trễ.

Vâng, vâng, nó là và nó sẽ trong một thời gian dài . Bạn có thể đọc thêm về TCP vs UDP tại đây .


8
TCP sử dụng các luồng byte thay vì datagram. UDP sử dụng datagram. Việc triển khai TCP tốt sẽ giữ cho các gói không theo thứ tự, nhưng không có nội dung nào của gói có thể được cung cấp cho ứng dụng trừ khi hoặc cho đến khi tất cả các gói trước đó được nhận. Do đó, nếu một gói bị mất, người gửi có thể không cần truyền lại tất cả mọi thứ theo gói bị mất, nhưng ứng dụng nhận sẽ không thấy bất cứ thứ gì qua gói bị mất cho đến khi gói đó được truyền lại (ngay lập tức ứng dụng sẽ thấy nội dung của nó gói và những cái sau nó).
supercat

@supercat Thật không may, TCP không có cách nào để nói với người gửi chính xác những gói đã làm và không nhận được. Nó chỉ có một cơ chế cho "Tôi đã nhận được tất cả các byte thông qua số thứ tự x." Nếu người gửi truyền lại các gói mà người nhận đã nhận, nó sẽ bỏ qua các bản sao.
thiệu lại vào

@reirab: Tôi nghĩ rằng có một số tiện ích mở rộng hiện đại có tính năng đó, mặc dù tôi không nghĩ rằng việc triển khai đã gửi dữ liệu lên tới byte # 1.050.000 nhưng chỉ nhận được acks cho dữ liệu lên tới 1.000.000, sau một giây không nghe thấy bất kỳ ack nào cho 1.000.000 đồng, bắt đầu bằng cách gửi một khối dữ liệu từ 1.000.000 đến 1.000.500 hoặc sau đó chờ phản hồi. Nếu nó nhận được ack cho dữ liệu lên tới 1.000.500 thì nó có thể truyền lại nhiều dữ liệu hơn; nếu nó nhận được ack cho dữ liệu lên tới 1.050.000 thì nó có thể bỏ qua việc truyền lại.
supercat

1
@Giorgio IP chỉ định không có gì về tín hiệu tương tự. Điều đó được thực hiện ở lớp vật lý. IP hoạt động hai lớp ở trên đó tại lớp mạng. IP không quan tâm đến việc liệu các bit có vượt qua sợi quang, liên kết vệ tinh hay modem quay số 14,4 kbps hay không. UDP và TCP là một lớp từ IP, ở lớp vận chuyển. Ngoài ra, như supercat nói, TCP trình bày giao diện truyền phát đến ứng dụng, không phải giao diện datagram như UDP.
thiệu lại vào

@supercat Hmm ... bạn có thể đúng về các tiện ích mở rộng hiện đại, mặc dù nó chắc chắn không phải là một phần của chuẩn TCP gốc. Một ACK chỉ có một số thứ tự. Tôi giả sử việc triển khai TCP thường sẽ bắt đầu truyền lại toàn bộ cửa sổ gửi nếu một gói bị bỏ thay vì chờ xung quanh toàn bộ RTT cho mỗi gói. Điều đó sẽ thêm một độ trễ lớn nếu một số gói liên tiếp bị mất vì rất ít lợi ích.
thiệu lại vào

9

TCP <- Giao thức điều khiển truyền dẫn . Nó được thực hiện để kiểm soát truyền tải.

TCP được tạo ra để trở thành một công dân mạng tốt và ngoại giao. Nó tập trung vào việc làm cho mạng trở thành một trải nghiệm tốt cho mọi người và sẵn sàng giảm thông lượng để đạt được điều đó. Nó điều chỉnh theo môi trường bằng cách thêm độ trễ . Lý do là ví dụ:

  • Người nhận phát hiện một gói bị thiếu, yêu cầu người gửi giảm tốc độ (giảm một nửa tốc độ trong một thời gian).
  • Người nhận phát hiện thứ tự gói đến sai (có thể họ đã thực hiện các đường dẫn mạng khác nhau), yêu cầu người gửi chậm lại - và btw, người nhận sẽ không chấp nhận các gói tiếp theo cho đến khi bị mất.
  • Người gửi phát hiện tắc nghẽn mạng (ví dụ: thời gian khứ hồi chậm), thêm độ trễ.
  • Người nhận không thể theo kịp tốc độ (bộ đệm đầu vào quá đầy), yêu cầu người gửi thêm độ trễ (điều khiển luồng).
  • Có một máy thu chậm duy nhất (khốn ping cao, crybaby, chúng được gọi là gì) trong số các máy thu, độ trễ (có thể) được thêm vào trong hộ gia đình.

Ngoài ra

  • Thuật toán của Nagle có thể giữ dữ liệu của người gửi, cho đến khi có nhiều hơn để gửi (để sử dụng các khung dữ liệu hiệu quả hơn). Thời gian dữ liệu quan trọng bị trì hoãn.
  • Tôi tin rằng các bộ định tuyến gia đình thông thường với wlan có thể làm những điều thông minh (làm chậm) để làm thông lượng TCP giữa nhiều máy khách (giao diện wlan là nút cổ chai, ngay cả khi trò chơi không sử dụng nó). Liên quan đến phát sóng / đa phương tiện, tức là. Dữ liệu "khác" có thể làm giảm thông lượng TCP của bạn.
  • TCP ACKnowledges mọi thứ, không cần thiết cho môi trường chơi game. Không có điểm nào trong ACKing mỗi bản cập nhật vật lý. Đủ để nhận biết ví dụ mỗi giây một lần, hoặc tương tự. Nếu một máy khách (hoặc một máy chủ) im lặng trong một thời gian dài hơn, thì đó là lúc để phản ứng.

Mặc dù vậy, TCP cung cấp con số cao nhất cho (dữ liệu truyền tổng thể) / (tổng thời gian tiêu thụ). Chỉ là nó không xảy ra chính xác khi bạn muốn nó xảy ra.

UDP không có cái nào trong số này. Nó bắn theo ý muốn của bạn , chỉ là người ta không thể mong đợi nó sẽ bắn trúng mỗi lần - trong khi mục tiêu phải thông báo rằng "bạn đã không bắn trong một thời gian dài, tại sao?". Người ta vẫn có thể tạo các gói ACK tùy chỉnh của riêng mình, đặt nhiều bản ghi vào một gói, v.v. Và cũng quan trọng, kiểm soát truyền tải NAT. UDP chắc chắn phù hợp với các game có nhu cầu độ trễ thấp.


1
Lưu ý: Thuật toán của Nagle có thể bị tắt, ví dụ như cho linux .
mucaho

Nagle có thể chống lại (và có thể được bỏ qua bằng cách đặt mọi gói thành "đẩy" bởi ứng dụng) trong khi đó, Ack Delayed hoạt động theo hướng có lợi cho TCP, nó cho phép người gửi đặt thêm byte vào dây cho đến khi cửa sổ gửi đầy (lý tưởng là lớn vì bộ đệm nhận ở phía bên kia) bất kể có nhìn thấy ack hay không.
Jeff Meden

4
Đó là giao thức điều khiển truyền dẫn .
ysdx

1
Nhập những từ này một triệu lần ... thx - đã sửa.
Bão tố

3

Bạn có thể so sánh sơ đồ đầu tiên của RFC 768 (UDP) với sơ đồ đầu tiên của RFCP 793 (TCP) trang 15 .

Cả hai đều hiển thị 16 bit cho một cổng nguồn của Google, theo sau là 16 bit cho một cổng đích của Google. Cả hai đều hiển thị 16 bit cho một tổng kiểm tra trực tuyến. Theo RFC 768, quy trình tổng kiểm tra của UDP giống như được sử dụng trong TCP.

Trong khi Độ dài của UDP kết thúc các chi tiết về sơ đồ của UDP, thì độ dài của TCP là một phần của một tiêu đề giả giả 96 bit được mô tả ở trang 15 và 16.

Đừng mong đợi TCP sẽ tốt hơn UDP. Điều đó đơn giản là không có khả năng xảy ra, vì nhiều lý do. Một là TCP đơn giản là có nhiều bit hơn. Vì vậy, nếu thiết bị có thể xử lý hiệu quả một số bit nhất định mỗi giây, điều đó sẽ cho phép nhiều gói UDP hơn các gói TCP.

Lý do khác là cách bắt tay ba chiều của TCP có nghĩa là người gửi phải chờ phản hồi. Yêu cầu này giới thiệu chi phí bổ sung mà UDP không xử lý. Có một lý do tại sao hầu hết các giao tiếp Internet của bạn bắt đầu với một số giao tiếp UDP. DNS cơ bản sử dụng UDP vì một yêu cầu và phản hồi có thể được hoàn thành trong ít bước hơn so với quy trình bắt tay ba bước của TCP. Tính năng theo dõi các gói bị mất của TCP khá khó chịu, bởi vì máy tính có thể chỉ cần thực hiện một yêu cầu mới thay vì cố gắng để một hệ thống từ xa biết rằng có một yêu cầu chưa được thực hiện trước đó.


Mặc dù tóm tắt bằng tiếng Anh (như đã thấy trong một số câu trả lời khác) là tốt, nhưng chỉ cần có một số mô tả chính xác và chính xác có thể là đơn giản nhất.
TUYỆT VỜI

Bạn có nghĩa là 16 bit, không phải byte!
jcaron

Ôi, tôi thật ngốc. 'đây là một ví dụ về lý do tại sao các câu trả lời chính xác về mặt kỹ thuật là tốt đẹp; họ rất dễ xác định lỗi và xem thông tin chính xác. Tôi đã sửa câu trả lời. Cảm ơn bạn @jcaron
TUYỆT VỜI

2

Hãy xem xét những gì đang xảy ra trong một khoảnh khắc. Để đơn giản hóa các kịch bản, bạn có hai lựa chọn khi cố gắng gửi thay đổi trạng thái (như người chơi của bạn vừa đổi hướng, hoặc bắn súng hoặc một số người chơi khác vừa đặt bom):

  1. Giữ phiên TCP mở và khi tắt bom, hãy gửi tin nhắn TCP cho tất cả người chơi (nếu có thể, xem bên dưới)
  2. Giữ cổng UDP lắng nghe và khi tắt bom, hãy gửi tin nhắn UDP cho tất cả người chơi bất kể trạng thái kết nối của họ

Giả sử không có bản cập nhật cần thiết ngay trước nó, thời điểm bản cập nhật số ít đó đến 1 vs 2 sẽ không khác nhau nhiều. Đó là một chuyến đi từ máy chủ đến máy khách. Nhưng, nói thay vì chỉ là một quả bom phát nổ, bạn đang cố gắng tiếp tục hoạt động của một người nào đó chạy qua một mê cung; dệt, vịt, bắn súng, v.v ... Trong trường hợp của UDP, mọi hành động sẽ được gửi trong một datagram, ngay khi nó xảy ra. Trong trường hợp TCP, mọi hành động sẽ được gửi trong một gói chỉ khi máy chủ được phép gửi. Điều gì nói rằng nó được phép gửi? Có chỗ trong cửa sổ TCP (giả sử ack bị trễ đang hoạt động) để tin nhắn có thể được đặt trên dây. Nếu không, nó phải đợi một ack đến từ khách hàng trước khi gửi.

Bao lâu là quá dài? Khi phát triển game bắn súng góc nhìn người thứ nhất nhiều người chơi đã sải bước trở lại vào cuối những năm 90 và đầu những năm 2000, kết nối độ trễ thấp không phổ biến. Một modem quay số sẽ có độ trễ một chiều thông thường là 180ms. Chờ đợi một ack trước khi gửi một bản cập nhật khác, hiệu quả gấp đôi thời gian đó lên 360ms, thật đau đớn; ngay cả người dùng mới làm quen chắc chắn có thể cảm thấy sự khác biệt. Khi các kết nối băng thông rộng bị bắt, chúng đã làm giảm độ trễ xuống rất nhiều nhưng nó vẫn tồn tại khi băng thông bị thiếu (khá thường xuyên ở một số khu vực). Vì vậy, ưu tiên cho độ trễ thấp nhất có thể vẫn tồn tại.

Các kết nối và kết nối nhà hiện đại đã thay đổi điều này, đến mức độ trễ của khu vực, ngay cả trong thời gian tắc nghẽn trong ngày, nằm trong phạm vi 15ms hoặc thấp hơn. Việc chọn TCP thay vì UDP sẽ vô hình trong hầu hết các trường hợp, vì độ trễ là "đủ thấp". Tuy nhiên, vẫn có xu hướng UDP được ưu tiên hơn TCP do lịch sử của nó là giao thức có độ trễ thấp. Vì vậy, hiện tại (và có thể một thời gian trong tương lai) UDP sẽ được ưu tiên cho giao tiếp thời gian thực.


Độ trễ sẽ đủ thấp, ngoại trừ theo mặc định, ghi TCP chỉ được gửi khi dữ liệu để ghi vượt qua một ngưỡng nhất định hoặc thời gian chờ (thường là 200-1000ms). Nếu bạn cần TCP trên hệ thống có độ trễ thấp với thông lượng nhỏ, bạn phải tắt tính năng này và đảm bảo rằng bạn không viết từng byte riêng lẻ (ví dụ: bạn không còn coi luồng TCP là luồng và bạn giả vờ thay vào đó là xử lý các tin nhắn cá nhân). Bạn không cần phải đợi ACK trừ khi bộ đệm của bạn đã đầy, điều này rất khó xảy ra trong một trò chơi thời gian thực thông thường.
Luaan

1
@Luaan Nhập: cờ TCP PSH. Khi một ứng dụng đưa nó xuống ngăn xếp, gói được gửi ngay lập tức mà không cần chờ thêm dữ liệu. Rất nhiều ứng dụng sử dụng thành công (ví dụ telnet và ssh).
Jeff Meden

2

Tôi biết rằng UDP thường được khuyên dùng cho các trò chơi nhiều người chơi trong thời gian thực với mức sử dụng dữ liệu cao
Có phải UDP vẫn vượt trội về tốc độ và độ trễ? Tối ưu hóa TCP gần đây có thể làm cho TCP hoạt động tốt hơn UDP không?

Giả định của bạn là sai. TCP và UDP khác nhau chủ yếu ở mô hình mà chúng đại diện (các datagram không đáng tin cậy so với luồng ảo đáng tin cậy theo thứ tự).

Chúng không khác nhau về khối lượng ("sử dụng dữ liệu cao") hoặc thông lượng. TCP sẽ đẩy qua nhiều dữ liệu như UDP, nó sẽ dễ dàng bão hòa cáp vật lý.

Trong trường hợp mất gói, cả hai làm khác nhau về độ trễ, nhưng chỉ trong điều kiện đó. Mặt khác, TCP có độ trễ thấp như UDP (cho hoặc mất khoảng vài chục nano giây vì ngăn xếp mạng có logic hơn một chút để làm, nhưng điều đó khá khó tin).
Có một sự khác biệt nhỏ về kích thước tiêu đề, vì vậy về mặt kỹ thuật, nhiều byte phải tạo ra nó trên dây trên các dòng nối tiếp, nhưng điều đó cũng khá không quan trọng. Nó chỉ thực sự quan trọng đối với chuyển khoản số lượng lớn, và sau đó chênh lệch 0,5%. Hầu hết mọi người có truy cập internet DSL tại nhà đều định tuyến tất cả lưu lượng truy cập của họ qua ATM, có thêm 10% chi phí giao thức (5 byte kiểm soát cho 48 byte tải trọng, cộng với các khung một phần) và thậm chí không ai nhận thấy.

Một số người xây dựng độ tin cậy trên UDP. Nếu một số mức độ tin cậy là mong muốn, nhưng việc cung cấp theo thứ tự nghiêm ngặt là không cần thiết, điều đó có thể mang lại một lợi thế nhỏ. Tuy nhiên, vẫn còn tranh cãi liệu cách tiếp cận này có nhiều ý nghĩa hay không, và bạn phải trả giá đắt cho lợi thế nhỏ bé đó.
Nếu bạn có các máy khách kết nối từ WiFis của khách sạn hoặc các địa điểm "kỳ lạ" khác, bạn sẽ nhận thấy rằng sự hỗ trợ chung cho TCP thường tốt hơn nhiều so với UDP.

Các trò chơi thường sử dụng UDP không phải vì nó vượt trội theo một trong những cách đã được đề cập - không phải - hoặc vì bạn có thể giảm jitter xuống nửa mili giây bằng cách thực hiện độ tin cậy mà không theo thứ tự, mà vì các trò chơi (giống như điện thoại IP) thường chứa rất nhiều dữ liệu rất dễ bay hơi, chẳng hạn như cập nhật vị trí ví dụ.
Dữ liệu dễ bay hơi này thường xuyên và nhanh chóng bị lỗi thời cả thời gian trôi qua và bởi các datagram tiếp theo xuất hiện. Điều đó có nghĩa là không có gì hơn và không có gì khác hơn là bạn thực sự không quan tâm quá nhiều đến việc đáng tin cậy 100% (hoặc theo thứ tự).

Giả sử một gói mạng bị bỏ trong một dịch vụ chạy với tốc độ ổn định với các bản cập nhật thường xuyên xuất hiện (trò chơi bắn súng, điện thoại, trò chuyện video), sẽ không có ý nghĩa gì khi hết thời gian thừa nhận và gửi lại gói, và trong khi đó đóng băng mọi thứ ở đầu bên kia trong khi chờ gói tin bực bội đến. Đó là cách quá đáng lo ngại, và không tốt.

Thay vào đó, bạn chỉ cần xem xét gói bị mất và tiếp tục, lấy dữ liệu từ gói tiếp theo để thực hiện và trong khả năng tốt nhất của bạn, che giấu sự thật rằng một gói bị mất khỏi người dùng. Nội suy, tính toán chết, bạn đặt tên cho nó.

Lưu ý bằng cách mất gói là một điều kiện bình thường. Mặc dù IP nói chung là "khá đáng tin cậy", các gói đôi khi bị bỏ có thể xảy ra và sẽ xảy ra . Mặc dù các gói bị mất thường là ở phía hiếm (<1% ở đây), nhưng đó không phải là một điều gì đó phi thường hoặc lý thuyết, hoặc là một dấu hiệu cho thấy một cái gì đó bị hỏng. Đó là điều hoàn toàn bình thường.
Mỗi lần chuyển số lượng lớn TCP nhất thiết sẽ bao gồm các gói bị mất, ví dụ (đó là cách điều khiển tắc nghẽn hoạt động).


2

Trong MPG băng thông cao, bạn không quan tâm nếu bạn bỏ lỡ một gói cung cấp cho bạn vị trí và sức khỏe của quái vật # 425, bởi vì bạn sẽ nhận được một bản cập nhật khác trong một vài giây. Đây là và ví dụ trong đó UDP làm cho TCP trông thật ngu ngốc khi khiến bạn chờ đợi dữ liệu lỗi thời ngay lập tức.

Trong cùng một trò chơi, bạn muốn các bản vá hiển thị chính xác như chúng được thiết kế. TCP đã tích hợp sẵn các tính năng "cho tôi biết nếu nó bị lỗi", tạo điều kiện cho việc thử lại tự động và các lỗi được xác minh. Bạn có thể làm điều đó trong UDP, nhưng tại sao phải tạo lại công nghệ?

Đây là một mô tả đơn giản về những gì đang xảy ra.

UDP - Cô lập chunk O'data.
Làm một gói.
Đóng gói trong IP.
Vận chuyển nó.

TCP - Cô lập một luồng O'data.
Tạo một gói từ phía trước của luồng.
Đóng gói trong IP.
Đợi không gian trong cửa sổ TCP.
Vận chuyển nó.
Tiếp tục chia sẻ lại cho đến khi nhận được hoặc hết thời gian.
Ở trong cửa sổ TCP cho đến khi nhận được hoặc hết thời gian.

Vận chuyển chỉ có nghĩa là nó đã được thực hiện thông qua NIC địa phương, không còn nữa.

Một nhận tiếp nhận TCP vừa đảm bảo nhận dữ liệu vừa giải phóng không gian trong cửa sổ cho gói tiếp theo.

Gửi lại (một chút) làm tăng khả năng nhận được cuối cùng.

Các gói TCP được lắp lại ở phía bên kia như một luồng dữ liệu theo thứ tự. Gói tin UPD được nhận dưới dạng gói riêng biệt. Giao thức không bảo toàn trật tự.

TCP tốt cho việc đẩy dữ liệu cần thiết và lượng dữ liệu được đặt hàng lớn. TCP cung cấp thông báo về một thất bại liên tục. TCP tự điều chỉnh thông qua các ống bị nghẹt (ref: window). TCP có những cái bắt tay để làm chậm quá trình khởi tạo. TCP yêu cầu "kết nối" trước khi truyền.

UDP chỉ cần đặt dữ liệu lên dây và cho phép bạn tiến hành mà không cần chờ cửa sổ và truyền lại. UDP sẽ thổi dữ liệu ở tốc độ tối đa vào một đường ống bị nghẹt, bất kể có bao nhiêu dữ liệu bị mất.

Tôi đã thiết kế và viết một tiện ích truyền tải tệp UDP Multicast được áp dụng thương mại. Tôi đã làm việc trên các ngăn xếp IP. Đây chỉ là những điều cơ bản, sans minutia. Giải thích "ổ cắm, MTU và đồ chơi vui nhộn khác" vượt xa những gì sẽ hữu ích cho câu hỏi này.

Ps (Tôi không thể thêm nhận xét để trả lời nhận xét) UDP cũng tốt cho dữ liệu mong muốn nhưng không bắt buộc. Sửa lỗi chuyển tiếp là một ví dụ về điều này, rất nhiều gói không cần thiết nhưng mong muốn.


3
Quan điểm của bạn về dữ liệu "lỗi thời" là một điều tốt. TCP tốt cho dữ liệu "muộn còn hơn không bao giờ", nhưng UDP tốt cho dữ liệu sẽ hữu ích nếu đến đích nhanh chóng, nhưng vô dụng nếu không.
supercat

1

Có phải tất cả các bộ định tuyến được tối ưu hóa TCP đã khiến TCP hoạt động tốt hơn UDP?

Một câu hỏi nữa là: "dữ liệu nặng" có nghĩa là bạn sẽ thường xuyên tải cảnh?

Nếu có, bạn có thể cần gửi các phần dữ liệu lớn (> 1k) trong đó TCP có thể hiệu quả hơn nhiều vì đặc biệt là về phía máy chủ, các NIC sẽ cung cấp nhiều tải khác nhau trong cùng một chu kỳ. Một ứng dụng không gian người dùng có thể phát hành ghi lớn với TCP trong khi trong UDP, một nỗ lực gửi nhiều hơn các byte kích thước tiêu đề MTU sẽ gây ra sự phân mảnh IP và các chi phí khác sẽ làm giảm hiệu suất


Đây là một trò chơi "voxel", vì vậy, nó sẽ cần gửi nhiều dữ liệu cảnh.
KaareZ

@KaareZ Chà, có lẽ bạn muốn gửi chúng dưới dạng tin nhắn độc lập riêng lẻ trong trường hợp đó bằng các cơ chế truyền lại của riêng bạn. Minecraft bắt đầu trên TCP và không thể phát được qua internet; việc chuyển sang UDP là một dịp vui vẻ với hầu hết mọi người. Ý tưởng chính là khi bạn gửi 20 khối dữ liệu voxel và dữ liệu đầu tiên bị "mất", nó không nên chặn 19 khối khác hiển thị ngay khi bạn nhận được dữ liệu; Khi bạn thấy rằng cái đầu tiên bị thiếu, bạn truyền lại. Trên TCP, tất cả 19 trong số đó bị đình trệ ít nhất và được truyền lại trong trường hợp xấu nhất.
Luaan

2
@Luaan Minecraft chưa chuyển sang UDP cho lối chơi thực tế. Ngay cả các phiên bản mới nhất vẫn sử dụng TCP. Không có dịp nào vui vẻ ... :( Phần duy nhất của Minecraft sử dụng UDP là danh sách máy chủ, để ping các máy chủ riêng lẻ và xác định xem chúng có trực tuyến hay không.
camerondm9

1

Cả UDP hoặc TCP (hoặc bất kỳ biến thể nào khác) đều vượt trội hơn hẳn , thậm chí không xét về tốc độ / độ trễ. Sự lựa chọn của bạn phải được thực hiện tùy thuộc vào yêu cầu của ứng dụng của bạn. Để làm điều này, bạn nên so sánh các tính năng mà mỗi giao thức cung cấp, nhận ra rằng nhiều tính năng hơn bao hàm nhiều chi phí hơn. Vì vậy, nếu mục tiêu là giảm thiểu độ trễ hoặc tối đa hóa tốc độ, thì bạn nên chọn một giao thức có càng ít tính năng càng tốt, nhưng trong khi vẫn giữ các tính năng thiết yếu cần thiết để đáp ứng yêu cầu của bạn.

So sánh các giao thức

Nói chung, UDP (Giao thức gói dữ liệu người dùng) cung cấp số lượng tính năng ít nhất. Nó đơn giản ở chỗ bạn gửi dữ liệu mà không cần bất kỳ loại nhận / xác nhận nào.

Mặt khác, TCP (Giao thức điều khiển truyền dẫn) cung cấp hầu hết các tính năng cần thiết cho một giao tiếp được kết nối, đáng tin cậy. Một giao tiếp TCP gửi các bản sao hoặc nhiều gói hơn và gắn thẻ chúng với thông tin đặt hàng. Khi nhận được tại đích, một ACK (xác nhận) phải được gửi lại cùng với thông tin về các gói bị mất để người gửi ban đầu có thể gửi lại các gói bị mất. Nếu tôi nhớ lại một cách chính xác, ngay cả các gói ACK có thể cần sự thừa nhận để có độ tin cậy phù hợp.


Ví dụ: Cuộc gọi hội nghị Skype

Đối với một cuộc gọi hội nghị Skype, việc đảm bảo rằng tất cả dữ liệu video và âm thanh được gửi / nhận một cách đáng tin cậy là không quan trọng. Ngày nay, UDP thực hiện một công việc tuyệt vời trong việc giảm thiểu việc mất gói tin. Điều quan trọng cần biết là hoàn toàn không có gì đảm bảo trong UDP cho dù việc truyền có thành công hay không. Đối với dữ liệu âm thanh / video trong cuộc gọi hội nghị, UDP là một lựa chọn phù hợp vì chúng tôi quan tâm nhiều hơn đến việc nhận dữ liệu thời gian thực (nghĩa là gần đây nhất). Nếu một vài gói bị mất ở đây và ở đó, nó sẽ không làm gián đoạn giao tiếp một cách kịch tính.

Tuy nhiên, trong cuộc gọi hội nghị, mọi người có thể gửi IM (tin nhắn tức thời) hoặc gửi tệp. Trong những trường hợp này, độ tin cậy là một yêu cầu cần thiết để đảm bảo rằng các tệp và tin nhắn không bị hỏng hoặc bị mất. Đối với IM, bạn có thể không cần trạng thái được kết nối mà TCP cung cấp. Một giao thức trung gian, chẳng hạn như RUDP (UDP đáng tin cậy) có thể là đủ. Tuy nhiên, đối với các tệp, có thể cần phải có trạng thái được kết nối mà TCP cung cấp.


Lựa chọn thực hiện

Nếu bạn có một ứng dụng phức tạp hoặc cần tối ưu hóa giao tiếp của mình, thì có ích khi bắt đầu với giao tiếp UDP. Sau đó, bạn có thể thêm tất cả các tính năng bạn cần lên trên. Điều này sẽ cung cấp cho bạn quyền kiểm soát nhiều nhất về giao tiếp mạng của bạn.

Nếu bạn có một ứng dụng đơn giản không yêu cầu tối ưu hóa, hãy cân nhắc sử dụng một tiêu chuẩn (UDP hoặc TCP) để đáp ứng nhu cầu của bạn. Điều đó sẽ cho phép bạn chuyển sang các vấn đề quan trọng hơn.


1

Tôi nhận thấy nhiều ý kiến ​​nơi mọi người tin rằng các gói TCP lớn hơn các gói UDP. Đừng tin tôi, hãy đọc tài liệu. Giao thức như sau: một vài byte cho tiêu đề Ethernet (loại thông báo 2 byte, MAC 48 bit, 6 byte) (đối với Wifi, tiêu đề có thể khác nhau) 20 byte cho IP 20 byte cho TCP hoặc UDP x byte cho dữ liệu x phạm vi từ 0 đến khoảng 1500 (xem MTU) Cuối cùng, tổng kiểm tra để đảm bảo rằng không có lỗi xảy ra trong gói Ethernet đó.

TCP cho phép gửi gói "luồng" lớn hơn khoảng 64K. Khối "lớn" này thực sự bị cắt nhỏ trong nhiều gói Ethernet nhỏ hơn.


Bạn đang cố gắng đề xuất rằng các tiêu đề UDP và TCP có cùng kích thước?
Cameron
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.