Veri yoğun gerçek zamanlı oyunlar için UDP hala TCP'den daha mı iyi?


71

UDP'nin genellikle yüksek veri kullanımına sahip gerçek zamanlı çok oyunculu oyunlar için önerildiğini biliyorum.

Makalelerin çoğu serval yaşındadır ve internette iletilen tüm verilerin ~% 80'i TCP olduğundan, TCP için çok fazla optimizasyon yapılması gerekir.

Bu beni meraklandırıyor: UDP hala hız ve gecikme açısından üstün mü? Son TCP optimizasyonları TCP'nin UDP'den daha iyi performans göstermesini sağlayabilir mi?


25
UDP ile, paketlerinizin alınacağına veya sipariş edileceğine dair hiçbir garanti yoktur; bu yalnızca UDP'yi TCP'den daha hızlı hale getirir.
nathan

4
@KaareZ Daha hızlı ne demek istiyorsun?
nathan

2
@nathan Uygulamanızı TCP ile geliştirmek UDP'den daha kolaydır. Tüm TCP optimizasyonlarının TCP'yi performans açısından daha iyi bir seçenek haline getirip getirmediğini bilmek istiyorum.
KaareZ

3
@ KaareZ Ben bir uzman değilim ama hadi düşünelim. TCP performans açısından nasıl daha iyi olabilir ve hala güvenilir bir protokol olabilir? Her şeye sahip olamazsın. TCP güvenilirlik için yapılmıştır. Asıl soru, oyunda neden TCP kullanmak istiyorsun?
nathan

7
UDP, TCP'den daha iyidir, ancak yalnızca (= deneyimli düşük seviyeli ağ programcısı), içinde ihtiyacınız olan TCP özelliklerini etkili bir şekilde yeniden uygularsanız uygulayabilirsiniz. Performans için gereksiz TCP özelliklerini düşürme.
wondra

Yanıtlar:


119

Hayır, UDP performans gecikmesi açısından hala üstündür ve 2 protokolün felsefesi nedeniyle her zaman daha hızlı olacaktır - iletişim verilerinizin UDP veya herhangi bir diğer kayıplı iletişim göz önünde bulundurularak tasarlandığını varsayarsak.

TCP, tüm ağ paketlerinin geldiği ve gönderildikleri sıra ile geldikleri bir soyutlama yaratır. Kayıp bir kanalda böyle bir soyutlamayı uygulamak için zaman harcayan yeniden iletimleri ve zaman aşımlarını uygulamalıdır. TCP'ye 2 güncelleme gönderirseniz ve ilk güncellemenin bir paketi kaybolursa, ikinci güncellemeyi şu tarihe kadar göremezsiniz:

  1. İlk güncellemenin kaybı tespit edildi.
  2. İlk güncellemenin tekrar iletimi isteniyor.
  3. yeniden iletme geldi ve işlendi.

Bunun TCP'de ne kadar hızlı olduğu önemli değil, çünkü UDP ile ilk güncellemeyi atıyor ve ikinci, daha yeni olanı kullanıyorsunuz. TCP'den farklı olarak, UDP tüm paketlerin geldiğini garanti etmez ve sırayla gelmelerini garanti etmez.

Bu, doğru türde veri göndermenizi ve iletişiminizi veri kaybetmeyi kabul edecek şekilde tasarlamanızı gerektirir.

Her paketin ulaşması gereken verileriniz varsa ve paketler oyununuz tarafından gönderildikleri sırada işlenmelidir, o zaman UDP daha hızlı olmaz. Aslında bu durumda UDP kullanmak muhtemelen daha yavaş olacaktır, çünkü TCP'yi yeniden yapılandırıyorsunuz ve bunu UDP aracılığıyla uyguluyorsanız, bu durumda TCP'yi de kullanabilirsiniz.

EDIT - Yorumların bazılarını eklemek / adreslemek için bazı ek bilgiler eklemek:

Normal olarak, Ethernet üzerindeki paket kaybı oranı çok düşüktür, ancak WiFi söz konusu olduğunda veya kullanıcının devam eden bir yükleme / indirme işlemi varsa, çok daha yüksek hale gelir. % 0.01 (tek yönlü, gidiş-dönüş değil) mükemmel homojen bir paket kaybımız olduğunu varsayalım. Birinci şahıs atıcıda, istemciler bir şey olduğunda, fare imlecinin oynatıcıyı döndürdüğü, saniyede yaklaşık 20 kez olduğu gibi güncellemeler göndermelidir. Ayrıca, kare başına veya sabit bir aralıkta güncellemeleri gönderebilirler; bu, saniyede 60-120 güncelleme olacaktır. Bu güncellemeler farklı zamanlarda gönderildiğinden, güncelleme başına bir pakette gönderilecek / gönderilmelidir. 16 oyunculu bir oyunda, 16 oyuncunun tamamı sunucuya saniyede 20-120 paket göndererek saniyede toplam 320-1920 paket gönderir. % 0.01 paket kaybı oranımızla, her 5.2-31.25 saniyede bir paket kaybetmeyi umuyoruz.

Kayıp paketten sonra aldığımız her pakette, bir DupAck göndereceğiz ve 3. DupAck'tan sonra gönderen kayıp paketi tekrar iletecek . Dolayısıyla, TCP'nin yeniden iletimi başlatması için gereken süre 3 paket, artı son DupAck'ın gönderene ulaşması için geçen süredir. Daha sonra yeniden iletimin gelmesini beklememiz gerekir, bu nedenle toplamda 3 paket + 1 gidiş dönüş gecikmesi bekleriz. Gidiş dönüş gecikmesi tipik olarak yerel bir ağda 0-1 ms ve internette 50-200 ms'dir. Saniyede 120 paket gönderirsek 3 paket tipik olarak 25 ms'de ve saniyede 20 paket gönderirsek 150ms'de gelir.

Bunun aksine, UDP ile bir sonraki paketi alır almaz kaybolan bir paketten kurtarıyoruz, bu yüzden saniyede 120 paket gönderirsek 8.3 ms, saniyede 20 paket gönderirsek 50 ms kaybediyoruz.

Nagle'ı (geliştirici birleştirmeyi göndermeyi unutursa veya gecikmeli ACK'yi devre dışı bırakamazsa) düşünmemiz gerekirse, TCP işleri daha da karışıklaşır , ağ tıkanıklığından kaçınmak veya paket kaybı birden fazla hesaba katmamız gereken kadar kötü ise paket kayıpları (kayıp Ack ve DupAck dahil). UDP ile daha hızlı kod yazabiliyoruz çünkü TCP gibi iyi bir ağ vatandaşı olmayı umursamıyoruz.


Not: UDP yerel ağı yayınlayabilir (olası avantaj) ve Vista, UDP'de sunucu / yayını çalıştırmak için yönetici gerektirdiğinden (dezavantajlı) (UAC / güvenlik duvarı, kullanıcının eylemini bildirmede başarısız olma eğilimindedir).
PTwr

7
"Eğer 2 TCP güncellemeleri ve ilk güncellemenin bir paket gönderirseniz kaybolur" Doğru, ama ne şansı o meydana için? Pingmen'e göre : "Bir süre içinde% 2'den fazla paket kaybının olması, sorunların güçlü bir göstergesidir."
mucaho

30
@ TCP'de bırakılan her paketin bir sonraki paketi durduğunu unutursun . 100ms ping ile, paket yeniden gönderilmeden ve alınmadan önce kolayca 300-500ms olabilir, bu nedenle her 33 saniyede bir durulan 6-10 paket vardır. Bu kesinlikle deprem benzeri bir FPS'de farkedilir olacak .
BlueRaja - Danny Pflughoeft

12
Pek çok TCP uygulamasında, cevapsız bir teybin ardından ilk zaman aşımı tam bir saniye alacaktır. Bu çok uzun bir zaman. Paketler küçükse, UDP cevapsız bir iletimden veya ikisinden kolayca kolayca akabilir, her paketin son iki güncellemeden veri içermesini sağlayarak uygulama gönderici veya alıcı ilk paketin kaybolduğunu bilmeden önce ihtiyaç duyduğu verileri alabilir.
supercat,

23
Quake gibi bir oyunda, ilk paketi kaybetmek önemli değil. Gelen FAR az zamanda daha çok kaybını tespit ve ilk paketi yeniden alacağını, zaten zaten eskimiş İlki kılan bir ikinci paket bulaşan gerekirdi. Bu, birçok gerçek zamanlı ses ve video uygulamasının UDP kullanmasıyla aynı nedendir. Bir paket düştüğünde, tüm akışı bir saniye veya daha fazla geciktirmek yerine 0.02 saniyelik ses kaybedersiniz. Bir nesne nerede olduğunu bilmek istiyorum aynı, gerçek zamanlı oyunlar ile genellikle doğru şimdi değil 1,5 saniye önce.
reirab

19

Hem TCP hem de UDP'nin IP üzerine kurulu protokoller olduğu konusunda hemfikiriz , değil mi? IP, iletilerin İnternet üzerinden nasıl iletildiğini belirtir, ancak iletinin yapısı, biçimi hakkında hiçbir şey yoktur. İşte TCP ve UDP protokolleri geliyor. IP özelliklerini kullanırlar, ancak programcının alt net iletişim katmanları hakkında endişelenmeden mesaj alışverişine odaklanmasına izin verir. Ve bu harika, çünkü tellerdeki analog sinyallerle doğrudan uğraşmak biraz acı verici olurdu.

  • TCP, mesaj göndermek ve almak için bir dizi işlev sunar. Verilerimizi kendimiz için küçük paketlere böler ve bunları ağ üzerinden gönderir. Tek istediğimiz ağ soketi için kullanılacak bir port ve göndermek istediğimiz gerçek mesaj. Ayrıca, algılandıkları ağ boyunca bazı paketler kaybolursa, gönderilmeleri gereken sırayla göndererek dikkatle tekrar gönderilir, bu güvenilirdir.

  • Diğer taraftan UDP, kullanıcı kontrolüne yönelik bir protokoldür. Datagramlarımızı göndermek için UDP kullanırken , datagramın hedefe ulaşıp ulaşamayacağından emin olamayız (ve burada matematiksel kesinliği kastediyoruz: bir paket gönderdiğimizde muhtemelen ulaşacaktır, ancak 100%). Ayrıca, bir paket kaybolduğunda ne algılanır ne de tekrar gönderilir.

Bu noktada, TCP tüm sorunlarımız için ideal bir çözüm gibi görünecektir. Güvenilir, hızlı, hangi paketlerin geldiğini ve hangi paketleri göndermemiz gerektiğini takip ederek bizim için bağlantı gecikmesini çözüyor.

AMA , ötesine bak. UDP'nin bize sağladığı tek avantaj, hızı ve gerçekten istediğimiz şey bu. Bir UDP paketi sadece hazırlanmış, özetlenmiş ve belirli bir kontrol olmadan gönderilir, çünkü UDP protokolü bu şekilde çalışır. Bir TCP paketi üretilmeli, etiketlenmeli, toplanmalı ve bir ACK geldiğinde gönderene "paket x burada, devam et" i bildirmek için geri gönderilmelidir ve bu sinyal gönderilmediğinde, bu paket x'in gönderilmesi gerektiği anlamına gelir. tekrar.

UDP'nin genellikle yüksek veri kullanımına sahip gerçek zamanlı çok oyunculu oyunlar için önerildiğini biliyorum.

Evet, ama sadece değil. UDP, çoğunlukla TCP üzerinden tercih edilir, çünkü yüksek hızı , yüksek veri gönderme ve yönetimi ile ilgili bir fikirdir. Bu, böyle bir video oyununun deterministic lockstep üzerinde çalıştığını farz edersek (sunucuda olan şey ağ gecikmesinden bağımsız olarak herhangi bir istemcide aynı şekilde çoğaltılır), bir güncelleme paketi kaybolur ve hiçbir zaman hedefine ulaşmaz. TCP böyle bir paketi tekrar gönderir ve sırayla gelmediği için aşağıdaki paketler düşer ve daha sonra kayıp paketten sonra yeniden gönderilir. UDP bu senaryoda çok daha hoşgörülü: bu paketle ilgilenmeyecek, çünkü yeni güncellemeler geliyor. Kayıp güncelleme yapılmaz, bunun yerine oyun fiziği kullanılan entegrasyon yöntemi ve en son güncelleme alındığında enterpolasyon yapılır .

TCP, gecikme süresi yeterince yüksek olduğunda titremeye neden olur, UDP şunları yapmaz:

<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>

Bu beni UDP'nin hız ve gecikme açısından hala üstün olup olmadığını merak ediyor.

Evet, öyle ve uzun zaman alacak . TCP ve UDP hakkında daha fazla bilgiyi burada bulabilirsiniz .


8
TCP, datagramlar yerine bayt akışlarını kullanır. UDP datagramları kullanır. İyi TCP uygulamaları, gelen paketleri sıra dışı tutacaktır, ancak önceki paketlerin tümü alınmadıkça ya da alınmadıkça, uygulama için hiçbir paket içeriği bulunamaz. Bu nedenle, bir paket kaybolursa gönderenin, kayıp paketi takip eden her şeyi yeniden iletmesi gerekmeyebilir, ancak alıcı uygulamanın, bu paket tekrar iletilinceye kadar kayıp paketin ötesinde bir şey görmemesi gerekebilir (bunun üzerine, uygulama anında içeriğinin içeriğini görecektir). paket ve ondan sonrakiler).
supercat,

@supercat Ne yazık ki, TCP'nin gönderene tam olarak hangi paketleri aldığını ve almadığını söylemenin bir yolu yoktur. Yalnızca "baytların tümünü x sekans numarası ile aldım." Mekanizmasına sahiptir. Gönderen, alıcının zaten aldığı paketleri yeniden gönderirse, kopyaları yok sayar.
reirab

@reirab: Bu özelliği içeren bazı modern uzantılar olduğunu sanmıştım, ancak onsuz 1.050.000 bayta kadar bir veri gönderen bir uygulamanın sadece 1.000.000'e kadar veri için bir not aldığını, ancak bir saniye sonra duymadığını söyledi. 1,000,000'den sonraki herhangi bir şey için herhangi bir teyit, 1,000,000 ila 1,000,500 arasında bir veri bloğu göndererek başlayın ve ardından yanıt bekliyor. 1.000.500'e kadar olan veriler için bir onay alırsa, daha fazla veriyi yeniden iletebilir; 1,050,000'e kadar olan veriler için bir onay alırsa, yeniden iletimi atlayabilir.
supercat,

1
@Giorgio IP, analog sinyaller hakkında hiçbir şey belirtmez. Bu fiziksel katmanda yapılır. IP, ağ katmanında iki kat daha çalışır. IP, bitlerin fiber üzerinden mi, bir uydu bağlantısından mı yoksa 14,4 kb / sn'lik bir çevirmeli modemden mi geçtiğini daha az önemsemedi. UDP ve TCP, IP'den taşıma katmanında bir katmandır. Ayrıca, supercat'ın dediği gibi, TCP UDP gibi bir datagram arayüzü değil, uygulamaya bir akış arayüzü sunar.
reirab

@supercat Hmm ... kesinlikle orijinal TCP standardının bir parçası olmasa da, modern uzantılar konusunda haklı olabilirsiniz. Bir ACK sadece bir sıra numarasına sahiptir. Bir TCP uygulamasının, normal olarak, her bir paket için bir RTT'nin etrafında beklemek yerine bir paket düştüğünde, gönderme penceresinin tamamını yeniden göndermeye başlayacağını varsayardım. Birkaç ardışık paket çok az kazanç için kaybedilmişse, bu büyük miktarda gecikme sağlayacaktır.
reirab

9

TCP <- İletim Kontrol Protokolü. İletimi kontrol etmek için yapılmış .

TCP iyi ve diplomatik bir ağ vatandaşı olarak kuruldu. Ağ oluşturmayı herkes için iyi bir deneyim haline getirmeye odaklanır ve bunu elde etmek için verimini isteyerek azaltır. Bu ayarlar ile çevreye gecikme ekleyerek . Sebepler örneğin:

  • Alıcı eksik bir paket tespit ettiğinde, gönderene yavaşlamasını söyler (oranı bir süre için yarıya indirir).
  • Alıcı yanlış gelen paket sırasını saptadı (belki farklı ağ yolları seçtiler), gönderene yavaşlamasını söyler - ve btw, alıcı, eksik olana kadar başka paketleri kabul etmez. Bu işlem zaman alır.
  • Gönderen, ağ tıkanıklığını algılar (örneğin, yavaş gidiş dönüş süresi), gecikme ekler.
  • Alıcı hıza ayak uyduramıyor (giriş arabelleği çok doluyor), göndericiden gecikme süresi eklemesini istiyor (akış kontrolü).
  • Alıcılar arasında tek bir yavaş alıcı (yüksek ping piç, ağlayan, ne denir), evde gecikme (eklenebilir) var.

bunlara ek olarak

  • Nagle algoritması gönderenin daha fazlasını bekletene kadar gönderenin verilerini beklemeye alabilir (veri çerçevelerini daha verimli kullanmak için). Zaman kritik veriler geciktiriliyor.
  • WLAN'lı sıradan ev yönlendiricilerinin birden fazla müşteri arasındaki TCP verimini yumuşatmak için akıllıca şeyler yapabileceğine (yavaşlayan) inanıyorum (oyun kullanmasa bile wlan arayüzü tıkanıklık oluyor). Örneğin yayın / çok noktaya yayın ile ilgilidir. "diğer" veriler TCP veriminizi düşürebilir.
  • TCP AC , bir oyun ortamı için gerekli olmayan her şeyi bilir . Her fizik güncellemesinde ACKing yapmanın bir anlamı yoktur. Örneğin saniyede bir kez veya benzer şekilde onaylamak için yeterli. Bir müşteri (veya bir sunucu) daha uzun süre sessizse, tepki verme zamanı gelmiştir.

Bunlara rağmen, TCP (toplam iletilen veri) / (toplam tüketilen süre) için en yüksek rakamı sağlar . Sadece bunun olmasını istediğinizde tam olarak gerçekleşmeyecek.

UDP bunların hiçbirini yapmıyor. Bu üzerine ateşler sizin kimse her zaman vurmak için bekleyemezsiniz sadece, irade - "neden, uzun zamandır vurmadım" hedef açıklamaları gerekir INSEAD'dan. Biri hala kendi ACK paketlerini yaratabilir, tek bir pakete birden fazla kayıt koyabilir, vb. Ve ayrıca önemli olan NAT geçişini kontrol etmektir. UDP, düşük gecikme talebine sahip oyunlar için kesinlikle uygundur.


1
Not: Nagle algoritması, örneğin linux için devre dışı bırakılabilir .
mucaho

Nagle karşı çalışabilir (ve her paketi uygulamanın "itmesi" için ayarlayarak yan yana koyulabilir), bu arada Gecikmeli Ack TCP'ler lehine çalışır, göndericinin gönderim penceresi doluncaya kadar (ideal olarak büyükse) telin üzerine daha fazla bayt koymasını sağlar alıcı tamponun diğer tarafta olduğu gibi) bir teybin görülüp görülmediğine bakılmaksızın.
Jeff Meden

4
Bu var iletim denetim protokolü.
ysdx

1
Bu kelimeleri milyon kere yaz ... thx - fixed.
Stormwind

3

Sen ilk diyagramı karşılaştırabilir RFC 768 (UDP) ilk şemasına RFCP 793 (TCP) sayfa 15 .

Her ikisi de “kaynak port” için 16 bit ve ardından “hedef port” için 16 bit gösterir. Her ikisi de bir "checksum" için 16 bit gösterir. RFC 768'e göre, UDP'nin “sağlama toplamı prosedürü TCP ile aynıdır”.

UDP'nin Uzunluğu, UDP'nin diyagramının ayrıntılarını tamamlarken, TCP'nin uzunluğu, sayfa 15 ve 16'da açıklanan “96 bitlik bir sözde başlığın” bir parçasıdır.

TCP'nin UDP'den daha iyi performans göstermesini beklemeyin. Bunun pek çok nedenden ötürü gerçekleşmesi muhtemel değildir. Birincisi, TCP'nin daha fazla bit olması. Bu yüzden eğer ekipman saniyede belirli bir bit sayısını etkili bir şekilde işleyebiliyorsa, TCP paketlerinden daha fazla UDP paketine izin verir.

Diğer bir sebep ise, TCP'nin “üç yollu el sıkışmasının” gönderenin bir yanıt beklemesi gerektiği anlamına gelmesidir. Bu gereksinim, UDP'nin yerine getirmediği ek yükleri de beraberinde getiriyor. İnternet iletişiminizin çoğunun bazı UDP iletişimi ile başlamasının bir nedeni var. Temel DNS UDP kullanır, çünkü bir istek ve yanıt TCP'nin “üç yönlü el sıkışma” işleminden daha az adımda tamamlanabilir. TCP'nin kayıp paketleri takip etme özelliği oldukça heyecan vericidir, çünkü bir bilgisayar uzaktaki bir sistemin yerine getirilmemiş bir önceki istek olduğunu bilmesini sağlamak yerine, yeni bir istek yapabilir.


Her ne kadar İngilizce özetler (diğer bazı cevaplarda görüldüğü gibi) güzel olsa da, sadece bazı doğru ve kesin açıklamalara sahip olmak en kolay yol olabilir.
TOOGAM

16 bit demek istiyorsun, bayt değil!
Jcaron

Ah, aptal ben. 'teknik olarak kesin cevapların neden güzel olduğunu gösteren bir örnek; hataları tanımlamak ve doğru bilgileri görmek kolaydır. Cevabı ben düzelttim. Thank you @jcaron
TOOGAM 21:16

2

Bir an için neler olduğunu düşünün. Senaryoları basitleştirmek için, bir durum değişikliği göndermeye çalışırken iki seçeneğiniz vardır (oynatıcınızın yeni yön değiştirmesi, bir silah vurması veya başka bir oyuncunun bomba atması gibi):

  1. Bir TCP oturumunu açık tutun ve bomba patlayacakken tüm oyunculara bir TCP mesajı gönderin (mümkünse aşağıya bakın)
  2. Bir UDP portunu dinlemeye devam edin ve bomba patlayacakken, bağlantı durumları ne olursa olsun tüm oyunculara bir UDP mesajı gönderin

Hemen bir güncellemenin gerekli olmadığını varsayarsak, bu tekil güncellemenin 1'e 2'ye ulaştığı zaman çok farklı olmaz. Sunucudan istemciye bir seyahat. Ancak, sadece bir bomba patlaması yerine, labirentten geçen birisinin etkinliğini sürekli olarak aktarmaya çalıştığınızı söyleyin; Dokuma, Ördek, Atıcılık, vb. UDP durumunda, her eylem bir anda gerçekleşir, bir datagram olarak gönderilir. TCP durumunda, her işlem yalnızca sunucunun gönderilmesine izin veriliyorsa bir pakette gönderilir. Göndermesine izin verildiğini söyleyen ne? Mesajın kabloya konulabilmesi için TCP penceresinde yer açmak (gecikmeli teyze etkin olduğu varsayılarak). Değilse, göndermeden önce istemciden bir teybin gelmesini beklemek zorundadır.

Ne kadar uzun? Çok oyunculu birinci şahıs nişancı gelişimi ortaya çıktığında 90'ların sonunda geri adım atıldı ve 2000'li yılların başında düşük gecikmeli bağlantılar yaygın değildi. Çevirmeli modem, tek yönlü 180ms gecikme süresine sahip olacaktır. Başka bir güncelleme göndermeden önce bir saat beklemek, o süreyi 360ms'ye iki katına çıkarmak, acı vericiydi; acemi kullanıcılar bile kesinlikle farkı hissedebiliyordu. Geniş bantlı bağlantılar bağlandığında gecikmeyi çok düşürdüler, ancak bant genişliği yetersiz olduğunda (bazı bölgelerde oldukça) devam etti. Bu yüzden mümkün olan en düşük gecikme süresi tercihi devam etti.

Modern ev bağlantıları ve ara bağlantılar, günün kısıtlı olduğu zamanlarda bile bölgesel gecikmenin 15 ms veya daha düşük bir aralıkta olduğu noktaya kadar değişmiştir. Gecikme "yeterince düşük" olduğu için UDP yerine TCP seçimi çoğu durumda görünmez olur. Bununla birlikte, UDP'nin düşük gecikmeli protokol olarak geçmişi göz önüne alındığında, TCP'ye öncelik verilmesi eğilimi hala devam etmektedir. Bu nedenle, şimdilik (ve muhtemelen gelecekte bir zaman olabilir) gerçek zamanlı iletişim için UDP tercih edilecektir.


Gecikme, varsayılan olarak, TCP yazma işlemlerinin yalnızca belirli bir eşiği veya bir zaman aşımı (genellikle 200-1000ms) geçtiğinde veri yazmaya yazıldığında gönderilmesi dışında, yeterince düşük olur. Çok az gecikmeli bir sistemde TCP'ye ihtiyaç duyuyorsanız, bu özelliği devre dışı bırakmanız ve her zaman tek tek bayt yazmadığınızdan emin olmanız gerekir (örneğin, artık TCP akışını akış olarak görmüyorsunuz ve bunun yerine bireysel mesajlarla uğraşıyoruz). Tamponlarınız dolu olmadıkça, tipik bir gerçek zamanlı oyunda olması muhtemel olmayan ACK'yı beklemeniz gerekmez.
Luaan

1
@Luaan Enter: TCP PSH bayrağı. Bir uygulama onu desteden aşağı indirdiğinde, paket daha fazla veri beklemeden derhal gönderilir. Birçok uygulama bunu başarıyla kullanır (örneğin, telnet ve ssh).
Jeff Meden

2

UDP'nin genellikle yüksek veri kullanımına sahip gerçek zamanlı çok oyunculu oyunlar için önerildiğini biliyorum
UDP hala hız ve gecikme açısından üstün mü? Son TCP optimizasyonları TCP'nin UDP'den daha iyi performans göstermesini sağlayabilir mi?

Varsayımların yanlış. TCP ve UDP temel olarak temsil ettikleri modelde farklılık gösterir (sıralı güvenilir sanal akışa karşı güvenilmez datagramlar).

Hacim ("yüksek veri kullanımı") veya verim açısından farklılık göstermezler. TCP, UDP kadar çok veriyi zorlayacak, fiziksel kabloyu kolayca doyuracak.

Paket kaybının varlığında, ikisi gecikme açısından farklılık gösterir , ancak yalnızca bu durumda. Aksi takdirde, TCP UDP kadar düşük gecikme süresine sahiptir (ağ yığını yapmak için biraz daha fazla mantık içerdiği için belki birkaç düzine nanosaniye veriniz veya alınız, ancak bu oldukça ihmal edilebilir).
Başlık boyutunda küçük bir fark vardır, bu yüzden teknik olarak, daha fazla bayt, seri hatlarda kablo üzerinden yapılmalıdır, ancak bu da oldukça önemsizdir. Sadece toplu transferler için gerçekten önemli ve% 0.5'lik bir farkla ilgili. Evde DSL internet erişimine sahip çoğu kişi, tüm trafiklerini% 10'luk protokol ek yükü ekleyen (48 baytlık yük için 5 kontrol baytı, ayrıca kısmi çerçeveler) ve hatta hiç kimse farketmeden ATM üzerinden yönlendirmektedir.

Bazı insanlar UDP'nin güvenilirliğini arttırıyor. Güvenilirlik bazı düzeyi arzu edilmektedir, ancak sıkı in-order kurtuluş gerekli değilse, o olabilir küçük bir avantaj sağlar. Ancak, yaklaşımın çok anlamlı olup olmadığı hala tartışmalıdır ve bu küçük avantaj için ağır bir bedel ödersiniz.
Otel WiFis veya diğer "garip" yerlerden bağlantı sağlayan müşterileriniz varsa, genellikle TCP için genel desteğin UDP'den çok daha iyi olduğunu fark edeceksiniz.

Oyunlar genellikle UDP'yi kullanmaz, çünkü yukarıda belirtilen yöntemlerden biri üstündür - öyle değildir - ya da siparişi vermeden güvenilirlik uygulayarak jitteri yarım milisaniyeyi azaltabilirsin çünkü oyunlar (IP telefonu gibi) genellikle konum güncellemeleri gibi çok fazla değişken veri içerir.
Bu geçici veriler, hem zaman geçtikten sonra, hem de bir sonraki datagram tarafından düzenli olarak ve hızla kullanılmazlar. Bu,% 100 güvenilir (veya sıralı) olmaktan çok fazla umrumda değil, hiçbir şeyden başka bir şey ifade etmez.

Bir ağ paketinin sürekli bir hızda çalışan bir hizmete düştüğünü varsayarak (shooter oyunu, telefon, video sohbeti) sık sık yapılan güncellemelerle bir paketin düşürüldüğünü kabul etmek, zaman aşımına uğramak ve paketi yeniden göndermek için çok fazla anlam ifade etmiyor. yeniden gönderilen paketin gelmesini beklerken diğer ucundaki her şeyi dondurun. Bu çok rahatsız edici ve iyi değil.

Bunun yerine, sadece bir paketin kullanıcıdan kaybedildiğini gerçeğini gizleyerek, paketin kaybolduğunu ve devam ettiğini, verilerini bir sonraki paketten geçirip verdiğini ve kabiliyetinizin en iyi şekilde olduğunu düşünün. İnterpolasyon, ölü hesaplaşma, siz adlandırın.

Paket kaybının normal bir durum olduğuna dikkat edin. IP genellikle "oldukça güvenilir" olsa da, zaman zaman atılan paketler gerçekleşebilir ve gerçekleşecek . Paketlerin kaybedilmesi normalde ender tarafta olsa da (burada <% 1), sıra dışı veya teorik bir şey değil, bir şeyin kırıldığının bir göstergesi değildir. Tamamen normal.
Her TCP toplu aktarımı mutlaka kayıp paketler içerecektir, örneğin (tıkanıklık kontrolünün nasıl çalıştığı).


2

Yüksek bant genişliğine sahip bir MPG'de, size # 425 numaralı canavarın yerini ve sağlığını veren bir paketi kaçırıp kaçırmamanız umrumda değil, çünkü bir saniyenin biraz daha başka bir güncellemesini alacaksınız. Bu ve UDP'nin TCP'yi aptal gibi görünmesine neden olarak anında eski veriler için beklemenizi sağlamasıdır.

Aynı oyunda, yamaların tasarlandıkları gibi görünmesini istiyorsunuz. TCP zaten yerleşiktir, "tekrar başarısız olursa bana bildir" özelliklerine sahiptir, otomatik yeniden deneme ve doğrulanmış hataları kolaylaştırır. UDP'de yapabilirsiniz, ancak neden teknolojiyi yeniden yarattınız?

İşte neler olduğuna dair basit bir açıklama.

UDP - O'data yığınını izole et.
Bir paket yap.
IP içine alın.
Onu yükle.

TCP - O'data bir Stream izole edin.
Akışın önünden bir paket yapın.
IP içine alın.
TCP penceresinde boşluğu bekleyin.
Onu yükle.
Bir makbuz alınana veya zaman aşımına uğrayana kadar yeniden göndermeye devam edin.
Bir makbuz alınana veya zaman aşımına uğrayana kadar TCP penceresinde kalın.

Nakliye sadece yerel NIC aracılığıyla gerçekleştirildiği anlamına gelmez.

Bir TCP makbuz alımı, hem veri alımını garanti eder hem de bir sonraki paket için pencerede yer açar.

Tekrar gönderme (hafifçe), nihai makbuz olasılığını artırır.

TCP paketleri diğer tarafa sipariş edilen bir veri akışı olarak yeniden monte edilir. UPD paketleri farklı paketler olarak alınır. Protokol siparişi korumaz.

TCP, gerekli verileri ve büyük miktarda sipariş edilen verileri zorlamak için iyidir. TCP kalıcı bir arıza bildirimi sağlar. TCP, boğulmuş borulardan kendi kendini keser (ref: penceresi). TCP başlatma işlemini yavaşlatmak için el sıkışmalarına sahiptir. TCP, iletimden önce bir "bağlantı" gerektirir.

UDP sadece verileri kabloya yerleştirir ve pencereleri ve yeniden iletimleri beklemeden devam etmenizi sağlar. UDP, ne kadar veri kaybı olursa olsun, verileri tam hızda boğulmuş bir boruya fırlatacak.

Ticari olarak uygulanan bir UDP Çok Noktaya Yayın Dosya Aktarımı Yardımcı Programını tasarlayıp yazdım. IP yığınları üzerinde çalıştım. Bunlar sadece temel şeyler, sans minutia. "Yuvaları, MTU'ları ve diğer eğlenceli oyuncakları" açıklamak, bu soru için faydalı olanın biraz ötesindeydi.

Ps (Yorumlara cevap yazmak için yorum ekleyemiyorum) UDP, istenen ancak gerekli olmayan veriler için de iyidir. İleri Hata Düzeltme bunun bir örneği, çok sayıda gereksiz ama istenen paket.


3
"Eski" verilerle ilgili düşünceleriniz iyi. TCP, "hiç olmadığı kadar iyi geç" verileri için iyidir, ancak UDP, hedefe hızlı bir şekilde ulaşması durumunda faydalı olacak veriler için iyidir, ancak yapmazsa işe yaramaz.
supercat

1

Tüm TCP için optimize edilmiş yönlendiriciler, TCP'nin UDP'den daha iyi performans göstermesini sağladı mı?

Bir soru daha: "ağır veri", sık sık sahneleri yükleyeceğiniz anlamına mı geliyor?

Evetse, yoğun olarak TCP'nin çok daha verimli olabileceği büyük miktarda veri (> 1k) göndermeniz gerekebilir, çünkü özellikle sunucu tarafında NIC'ler aynı devirlerde çok fazla boşaltma sağlar. Bir kullanıcı alanı uygulaması TCP ile büyük yazılar yazarken, UDP’de MTU başlıkları boyut bayttan daha fazla gönderme denemesi IP’nin parçalanmasına ve performansın düşmesine neden olacak diğer genel masraflara neden olur


Bu bir "voksel" oyunu, bu yüzden evet, çok fazla sahne verisi göndermesi gerekecek.
KaareZ

@KaareZ Muhtemelen, her durumda, kendi gönderim mekanizmalarınızla, bunları zaten bireysel bağımsız mesajlar olarak göndermek istersiniz. Minecraft TCP'de başladı ve internet üzerinden oynanamaz hale geldi; UDP'ye geçiş çoğu insan için mutlu bir fırsattı. Ana fikir, 20 parça voksel verisi yolladığınızda, birincisinin “kaybolması” olduğu zaman, diğer 19 parçanın veriyi alır almaz göstermesini engellememesi gerektiği; ilki eksik olduğunu bulduğunda, yeniden iletirsin. TCP'de, bu 19 kişinin hepsi en azından durdurulur ve en kötü durumda yeniden iletilir.
Luaan

2
@Luaan Minecraft gerçek oyun için UDP'ye geçmedi. En yeni sürümler bile hala TCP kullanıyor. Mutlu bir fırsat yok ... :( UDP kullanan Minecraft'ın tek kısmı, bireysel sunucuları ping edip çevrimiçi olup olmadıklarını belirlemek için sunucu listesi.
camerondm9

1

Ne UDP, ne de TCP (veya başka bir varyant), hız / gecikme açısından bile üstün değil. Seçiminiz, uygulamanızın gereksinimlerine bağlı olarak yapılmalıdır. Bunu yapmak için, her bir protokolün sunduğu özellikleri karşılaştırmalı, daha fazla özelliğin daha fazla ek yük gerektirdiğinin farkına varmalısınız. Bu nedenle, amaç gecikmeyi en aza indirmek veya hızı en yükseğe çıkarmaksa, o zaman mümkün olan en az özellik içeren bir protokol seçmelisiniz, ancak gereksinimlerinizi karşılamak için gereken temel özellikleri korurken.

Protokollerin Karşılaştırılması

Genel olarak, UDP (Kullanıcı Datagram Protokolü) en az miktarda özellik sunar. Herhangi bir makbuz / onay almadan veri göndermeniz oldukça basittir.

Öte yandan, TCP (İletim Kontrol Protokolü), güvenilir ve bağlı bir iletişim için gereken en fazla özelliği sunar. Bir TCP iletişimi kopyaları veya daha fazla paket gönderir ve bunları sipariş bilgileriyle etiketler. Hedefe ulaştıktan sonra, asıl gönderenin bu kayıp paketleri tekrar gönderebilmesi için hangi paketlerin kaybolduğu bilgisi ile birlikte bir ACK (onay) geri gönderilmelidir. Doğru hatırlıyorsam, ACK paketlerinin bile uygun güvenilirlik için onay alması gerekebilir.


Örnek: Skype Konferans Araması

Skype konferans araması için, tüm video ve ses verilerinin güvenilir bir şekilde gönderilmesini / alınmasını sağlamak önemsizdir. Günümüzde, UDP zaten paket kaybını asgariye indirmede harika bir iş çıkarmaktadır. Bilinmesi gereken önemli şey, UDP'de aktarımın başarılı olup olmadığına dair hiçbir garanti olmadığıdır. Bir konferans görüşmesindeki ses / video verileri için, UDP uygun bir seçimdir, çünkü gerçek zamanlı veri almayı daha fazla önemsiyoruz (yani en yeni olanı). Burada ve orada birkaç paket kaybolursa, iletişimi dramatik bir şekilde kesintiye uğratmaz.

Ancak, bir konferans görüşmesinde, insanlar IM'leri (anlık mesajlar) gönderebilir veya dosya gönderebilir. Bu durumlarda, dosya ve mesajların bozulmamasını veya kaybolmamasını sağlamak için güvenilirlik gerekli bir gerekliliktir. IM'ler için , TCP'nin sağladığı bağlı duruma ihtiyacınız olmayabilir . RUDP (Reliable UDP) gibi bir ara protokol yeterli olabilir. Ancak, dosyalar için TCP'nin sağladığı bağlı duruma sahip olmak gerekli olabilir.


Uygulama Seçenekleri

Karmaşık bir uygulamanız varsa veya iletişiminizi optimize etmeniz gerekiyorsa, UDP iletişimiyle başlamanız faydalı olacaktır. Daha sonra ihtiyacınız olan tüm özellikleri üste ekleyebilirsiniz. Bu size ağ iletişiminiz üzerinde en fazla kontrolü sağlayacaktır.

Optimizasyonun gerekli olmadığı basit bir uygulamanız varsa, ihtiyaçlarınızı karşılamak için standartlardan birini (UDP veya TCP) kullanmayı düşünün. Bu, daha önemli konulara geçmenizi sağlayacaktır.


1

İnsanların TCP paketlerinin UDP paketlerinden daha büyük olduğuna inandığı birçok yorum gördüm. Sadece bana güvenme, belgeleri oku. Protokol aşağıdaki gibidir: Ethernet başlığı için birkaç bayt (2 bayt mesaj türü, 48 bit MAC, 6 bayt) (Wifi için, başlık farklı olabilir) TCP için U 20 x bayt veya x x aralığında değişen UDP x bayt 0 ile 1500 arası (bkz. MTU) Son olarak, bu Ethernet paketinde bozulma olmadığından emin olmak için sağlama toplamı.

TCP, yaklaşık 64K'lık daha büyük "akış" paketini göndermeye izin verir. Bu "büyük" blok aslında pek çok küçük Ethernet paketinde doğranmış.


UDP ve TCP başlıklarının aynı boyutta olduğunu öne sürmeye mi çalışıyorsunuz?
Cameron,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.