UDP kullanarak onay güvenilirliği


16

UDP hakkında bir sorum var. Bağlam için gerçek zamanlı bir aksiyon oyunu üzerinde çalışıyorum.

UDP ve TCP arasındaki farkları biraz okudum ve onları oldukça iyi anladığımı hissediyorum, ancak hiç doğru hissetmeyen tek bir parça var ve bu güvenilirlik ve özellikle teşekkür ediyor . UDP'nin varsayılan olarak güvenilirlik sağlamadığını anlıyorum (yani paketler atılabilir veya sipariş dışı olabilir). Bazı güvenilirlik gerektiğinde, gördüğüm çözüm (kavramsal olarak mantıklıdır) onayları kullanmaktır (yani sunucu istemciye bir paket gönderir ve istemci bu mesajı aldığında, sunucuya bir onay gönderir) .

Kabul iptal edildiğinde ne olur?

Yukarıdaki örnekte (bir istemciye bir paket gönderen bir sunucu), sunucu bu paketler için onaylar alınana kadar paketleri her kareyi yeniden göndererek potansiyel paket kaybını ele alır. Hala bant genişliği veya bozuk mesajlarla karşılaşabilirsiniz, ancak yalnızca paket kaybı açısından sunucu kapsanır.

Ancak, istemci hiçbir zaman ulaşmayacak bir bildirim gönderirse, sunucunun bu mesajı göndermeyi durdurmaktan başka seçeneği kalmazdı, bu pakette bulunan bilgiler gerekirse oyunu bozabilir. Sunucuya benzer bir yaklaşım uygulayabilirsiniz (yani, ack için bir ack alana kadar onay göndermeye devam edebilir misiniz?), Ancak bu yaklaşım sonsuza kadar geri dönmenizi sağlayacaktır (ack için ack için bir ack'e ihtiyacınız olacağı için) ve bunun gibi).

Temel mantığımın burada doğru olduğunu hissediyorum, bu da beni iki seçenekle bırakıyor.

  1. Tek bir onay paketi gönderin ve en iyisini umun.
  2. Bir avuç onay paketi gönderin (belki 3-4) ve hepsinin düşürülmeyeceğini varsayarak en iyisini umun.

Bu sorunun bir cevabı var mı? Temelde bir şeyi yanlış mı anlıyorum? Farkında olmadığım UDP kullanma garantisi var mı? Mantıkımın sağlam olduğundan rahat olana kadar çok fazla ağ kodu ile ilerlemekte tereddüt hissediyorum.


11
Belki de "zaman aşımları" ve "yeniden denemeler" fikrini kaçırıyorsunuzdur.
Kromster, Monica

Emin olabilirim. Mantığımın doğru olduğunu ve çok olumsuz görünmeyeceğini söylüyorsunuz, ancak ağ programlama yaparken, ağa bağlı herhangi bir bilgi parçası için herhangi bir garanti alamıyorum? Gerçek zamanlı bir oyun sırasında, bu bir ton potansiyel olarak bırakılan bilgi, bu iyi, ama sadece sorunu anladığımdan emin olmak istiyorum.
Grimelios

10
Hiç garanti yok. Sağ. Algoritmalarınıza asla "umut" eklemeyin. HERHANGİ şanssız kombinasyonları ele almalıdırlar. PS Eberything'in halledildiği RTS'imizde TCP'ye geçtik, çünkü güvenilir iletişime ihtiyacımız var (kilit adım simülasyonu için).
Kromster, Monica

5
Güvenilirlik gerektiğinde TCP kullanın, önemli olmadığında UDP kullanın. Örneğin, oyuncunun koordinatları oyunumda UDP ile gönderiliyor. Eksik paketleri temizlemek için enterpolasyon ve yumuşatma kullanıyorum. tıkır tıkır çalışıyor. güvenilir olması gereken ancak biraz daha yavaş olabilecek şeyler TCP üzerinden gönderilir. Daha yeni bir devletin eski devleti geçersiz kılacağı bir durumunuz varsa, UDP iyi bir seçimdir, çünkü aradaki bir şeyin 8e.g düşmesi önemli değildir. oyuncu pozisyonu).
Polygnome

Bu, sorunuzun doğrudan bir yanıtı değildir, ancak gerçek zamanlı bir oyunda kesinlikle gerekli olduklarında (örn. İlk bağlantıda) bir onay almanızı şiddetle tavsiye ederim. Mümkünse durum bilgisi olmayan bir sistemde yeni bir paket alana kadar "sahip oldukları şeyle" çalışacak şekilde hem istemciyi hem de sunucuyu tasarlamak çok daha basittir (ve sağlamdır). Quake 3 bunu anlık görüntü tabanlı bir sistemle inanılmaz derecede iyi yaptı . Ayrıca Enet gibi kütüphaneler, gerçekten ihtiyacınız olan durumlarda sadece belirli paketleri güvenilir bir şekilde gönderebilir
jrh

Yanıtlar:


32

Bu, İki General Sorununun bir biçimidir ve haklısınız - makbuzu mükemmel bir şekilde garanti etmek için hiçbir yeniden deneme yeterli değildir.

Oyunlarda pratikte, teknik olarak güvenilir bir şekilde gelse bile, bilginin gerçekten önemli olmadığı bir zaman ufku vardır. 2 saniye önce mükemmel bir kafa vuruşuna sahip olduğunuzu öğrenmek gibi - oyuncunun bu bilgileri şimdi kullanması için çok geç.

Paket kaybınız o kadar yüksekse, gerekli bilgileri rutin bir şekilde sıkı bir reaksiyon penceresi içinden alamazsınız, o zaman gerçek zamanlı bir oyun için oyuncuyu tekmelemek ve onlar için başka bir yerde daha iyi bir eşleşme bulmaya çalışmaktan daha iyi olabilirsiniz. güvenilir bir bağlantı taklit etmek için paketi göndermeye devam edin.

Bu nedenle, bazı oyun çoğaltma sistemleri onaylamayı atlar ve yeniden dener ve en yeni güncelleştirmeyi olabildiğince sık spam olarak seçer. Biri düşerse veya çok geç gelirse, çok kötü, atlayın, bir sonrakini alın ve devam edin, boşluğu düzeltmek ve oyuncu tarafından görülen hıçkırıkları en aza indirmek için tahmin ve enterpolasyon sistemlerine güvenerek.

Aniden, geçmişte problemleri nasıl göz ardı ettiği ve şimdiki zamanda yaşamaya çalıştığı için bu "Simba Replikasyonu" adını vermeye başlamak istiyorum. ;)

Rafiki laying down some reductio ad absurdum on that life philosophy

Hibrit bir çözüm, yeni güncellemeyi göndermek için ileriye doğru yarışmaktır VE (oyun durumu güncellemeleri genellikle oldukça küçük / sıkıştırılabilir olduğundan ) son güncellemeyi de paketleyebilir ve belki ondan önce olanı ... Yani istemci onları kaçırdığında , bulmak ve düzeltmek için tam bir yolculuk süresi beklemek zorunda değilsiniz. Çoğu zaman istemci bunu zaten gördü, bu nedenle bu şekilde gereksiz veriler var, ancak cevapsız bir mesajı düzeltme gecikmesi daha düşük. İstemcinin güncellemeleri, gördükleri en son ardışık güncelleştirmenin dizin numarasını içerebilir, böylece bir sonraki güncelleme paketine kaç tane eski güncelleştirmeyi eklediğiniz konusunda en az tutucu olabilirsiniz.

Ayrıca, kısa ömürlü durumun güvenilir olmayan hızlı ateş tarzında çoğaltıldığı ve uzun vadeli durumun TCP veya kendi güvenilirlik uygulamanızı yüksek bir yeniden deneme ile güvenilir bir şekilde senkronize edildiği başka bir hibrit türü olarak iki katmanlı bir sistem de uygulayabilirsiniz. Miktar. Bu, yönetmek için daha karmaşık hale gelir, çünkü bakım yapmak için iki mesajlaşma sisteminiz vardır ve iki anlık görüntü, birbiriyle senkronize olmayabilir ve yepyeni bir kenar durumu sınıfı ekler.


1
+1, iyi yazılmış. Sadece bunun aksiyon / gerçek zamanlı oyunlarla daha alakalı olduğunu vurgulamak isterim. TBS ve RTS oyunları (ve bazı aksiyon oyunlarının etkinlikleri) "bilginin gerçekten önemli olmadığı zaman ufkunda" farklı bir görüşe sahiptir.
Kromster, Monica

3
Evet, sıra tabanlı bir oyun için, birinin kendi güvenilirlik katmanını UDP'nin üstüne yuvarlamak yerine TCP kullanacağını düşünürdüm. ;) Yine de, bir RTS'de mikroyu titiz bir zaman ufku olan bir oyun türü olarak sınıflandırırdım - o melez yaklaşım, o anın ısısı için düşük gecikmeli güncellemelerin yanı sıra kaynak harcamaları gibi önemli kaçırılmış olayları geriye dönük olarak ele almak için güvenlik ağı.
DMGregory

Bu son derece yararlı ve ilk endişemi doğrulıyor. Çok teşekkür ederim.
Grimelios

2
İleri Hata Düzeltmesinden bahsetmek de yararlı olabilir. Protokolünüzü, alıcının bir sonraki paket alındığında bir paketin bırakıldığını bağımsız olarak anlayabileceği şekilde tasarlayın ve gerekli enterpolasyonu düzeltmek için bazı ekstra veriler ekleyin. Bu yararlı olabilir, çünkü çoğu zaman UDP paketleri zaten dolu değildir ve gecikmeyi azaltmak için daha küçük paketleri daha sık gönderirsiniz. Fazladan bayt eklemek gecikmeye zarar vermez ve bant genişliği bu durumlarda bir sorun oluşturmaz.
MSalters

@ MSalters Eğer buna hazırsanız, kendi cevabında bunun üzerinde durmaya değer olduğunu söyleyebilirim. Bunu vuracağım. :)
DMGregory

9

TCP'nin kullandığı yaklaşım, gönderenin bir onay alana kadar paketi yeniden göndermeye devam etmesidir. Alıcı, yinelenen paketleri yok sayar, ancak yine de onlar için teşekkür gönderir. Gönderen, yinelenen onayları yok sayar.

Bir paket kaybolursa, gönderici bildiğiniz gibi yeniden gönderir.
Bir onay kaybolursa, gönderen, orijinal paketi tekrar gönderir ve bu da alıcının onayı yeniden göndermesine neden olur.

Belli bir süre içinde bir onay alınmazsa (belki 60 saniye veya 20 tekrar), oyuncunun oyunla bağlantısı kesilmiş sayılır. Sen gerekir zaman aşımı kuralının aksi halde ağ kablosu sonsuza sunucu üzerinde kaynaklarını bağlayabilir olacak unplugs bir oyuncunun bir çeşit uygulamak.


TCP'nin önemli bir özelliği, gönderenin belirli bir paketin kabul edilip edilmediğini önemsemesine gerek olmaması , ancak çoğunlukla "yüksek su işareti" ve yüksek su işareti hareket etmeden paketlerin ne kadar uzun süre beklediğini önemsemesi gerektiğidir.
Supercat

1
@supercat Bunun gerekli olduğunu söyleyemem; bir optimizasyon gibi.
user253751

Parantez içindeki şeyle ilgili olarak (zaten aldığınız paketler için ACK gönderme), bence bunu parantez yerine vurgulamanız gerekir. OP'nin anlayışından (veya en azından açıklamasından) eksik gibi görünüyor.
Angew artık SO

@Yeni şimdi yapıldı.
user253751

6

TCP'yi yeniden icat etmek istiyorsanız, ilk önce açıkladığınız sorunla ilgilenen TCP'ye bakmak mantıklıdır (çözümün bir kısmı, yeniden deneme girişimleri ve zaman aşımları için kullanıcı tanımlı değerleri kullanmaktır).

2 kanal, bir TCP kanalı (güvenilir iletişim için) ve bir UDP (düşük gecikme süresi iletişimi için) kanalı kullanan çözümler nadir değildir.

Bazı çözümler, bir istemcinin çok uzun süre bazı bilgileri eksik olduğunu algılar ve UDP veya TCP kullanabilen bir yeniden eşitleme başlatır.

Başka bir yaygın yaklaşım, iletişimi, hiç bir şekilde kabul edilmeyecek şekilde tasarlamaktır, ancak bu sorunun kapsamı dışındadır.


3

Bir RTS'de TCP gibi bir protokolü gerçekten kullanamazsınız ve UDP'yi de güvenilir hale getiremezsiniz. Eğer denerseniz, bir ağ bağlantısı olduğunda oyun donacaktır.

Bunun yerine, protokolü, kaçırılan paketlerin çok fazla önemli olmayacağı şekilde tasarlarsınız.

Kısa versiyon, şu anda nerede olduklarını bildiğiniz sürece diğer oyuncuların son karenin nerede olduğunu umursamamanızdır . Uzun versiyon daha karmaşıktır.

Daha sonra soru, bir paket kaybolduğunda ne yaparsınız? Ve cevap ... sanırım. Oyuncu muhtemelen düz bir çizgide ilerliyor, değil mi? Onları bu çizgi boyunca bir adım ileri taşıyın. ... hayır RTS oyuncu hariç hiç bir çizgide hareket eder. Ve sonra bir çarpışma tespiti var.

Bu zor. Birçok oyun yanlış anlıyor. Buna doğru bir cevap olmadığı, sadece takas edilebilecek çeşitli yanlışların olduğu iddia edilebilir.

Bu oyunların iyi çalışmasının nedeni, sadece bu sorunlar hakkında uzun ve zor düşündükleri değil, aynı zamanda internetin oldukça güvenilir hale gelmesidir. Hemen hemen tüm UDP paketleri hedeflerine zamanında ulaşır. (Güvenlik duvarı gibi kalıcı bir sorun olmadığı sürece)


Warcraft 3 TCP kullanıyor.
fsp
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.