UDP engellemiyor mu yoksa almak için ayrı bir iş parçacığı mı?


10

Çok oyunculu bir oyun oluşturuyorum (64 yaş altı oyuncular için). Zaten ağ döngüsü için ayrı bir iş parçacığına sahip olmaya karar verdim, ancak UDP almak için ekstra bir iş parçacığı oluşturmak veya alıcı soketi engellemeyen (ekstra iş parçacığı olmadan) ayarlamak daha iyi olacağını merak ediyordum.

Veya Asenkron Soketler gibi başka bir yöntem kullanmak daha mı iyi? Daha iyi yöntemler her zaman bekleriz!

Yanıtlar:


6

Tamam, her şeyden önce, eğer bir şeyiniz varsa ve işe yarıyorsa, bunu böyle bırakmak genellikle iyi bir fikirdir. Kırılmayan şeyi neden düzeltmeliyim?

Ancak sorun yaşıyorsanız ve gerçekten ağ kodunuzu yeniden yazmak istiyorsanız, dört ana seçeneğiniz olduğunu düşünüyorum:

  1. Çok iş parçacıklı engelleme kodu (şu anda ne yapıyorsunuz)
  2. Seviye tetiklemeli bildirim ile tıkanmayan soketler
  3. Hazırlık değişikliği bildirimi ile tıkanmayan soketler
  4. Asenkron prizler

Çok sayıda çok oyunculu (eşler arasıdan çok oyunculuya kadar) çok sayıda istemci ve sunucu yazdıktan sonra, seçenek 2'nin oyunun hem sunucu hem de istemci bölümleri için oldukça iyi performansla en az karmaşıklığa yol açtığını düşünüyorum. Yakın bir saniye olarak, seçenek 4 ile giderdim, ancak bu genellikle tüm programınızı yeniden düşünmenizi gerektirir ve çoğunlukla istemciler için değil sunucular için yararlı buluyorum.

Özellikle, çok iş parçacıklı bir ortamda soketlerin engellenmesine karşı tavsiyede bulunmak istiyorum, çünkü bunu yapmak genellikle kodun karmaşıklığını büyük ölçüde artırmakla kalmayıp aynı zamanda bazı iş parçacıkları bekledikçe performansını da düşürebilen kilitleme ve diğer senkronizasyon özelliklerine yol açar. diğerleri.

Ancak tüm bunların ötesinde, çoğu soket uygulaması (ve oradaki çoğu G / Ç uygulaması) en düşük düzeyde engellemez. Önemsiz programların geliştirilmesini basitleştirmek için engelleme işlemleri basitçe sağlanır. Bir soket bloke olduğunda, o iş parçacığındaki CPU tamamen boşta, o zaman neden zaten engellemeyen bir görev üzerinde engelleme soyutlaması üzerinde engellemeyen bir soyutlama oluştursun?

Engellemeyen soket programlama, denemediyseniz biraz yıldırıcıdır, ancak oldukça basittir ve zaten giriş yoklaması yapıyorsanız, engellemeyen soketler yapmak için zaten zihniniz var.

Yapmak istediğiniz ilk şey soketi engellemeyecek şekilde ayarlamaktır. Bunu ile yaparsın fcntl().

Bundan sonra, bunu yapmadan önce send(), recv(), sendto(), recvfrom(), accept()( connect()çağrı, iplik engelleyebilir veya diğer aramalar biraz farklıdır) select()soket üzerinde. select()sonraki bir okuma veya yazma işleminin soket üzerinde engellemeden gerçekleştirilip gerçekleştirilemeyeceğini bildirir. Bu durumda, istediğiniz işlemi güvenli bir şekilde yapabilirsiniz ve soket bloke olmaz.

Bunu bir oyuna dahil etmek oldukça basittir. Zaten bir oyun döngünüz varsa, örneğin şöyle:

while game_is_running do
    poll_input()
    update_world()
    do_sounds()
    draw_world()
end

şöyle görünecek şekilde değiştirebilirsiniz:

while game_is_running do
    poll_input()
    read_network()
    update_world()
    do_sounds()
    write_network()
    draw_world()
end

nerede

function read_network()
    while select(socket, READ) do
        game.net_input.enqueue(recv(socket))
    end
end

ve

function write_network()
    while not game.net_output.empty and select(socket, WRITE) do
        send(socket, game.net_output.dequeue())
    end
end

Kaynaklar açısından, herkesin kitap raflarında olması gerektiğini düşündüğüm tek kitap, sahip oldukları tek kitap olsa bile , Richard Stevens'ın sonundaki " Unix Network Programming, Cilt 1 " dir. Windows veya başka bir işletim sistemi veya dil soketi programlama yapmanız önemli değildir. Bu kitabı okuyana kadar soketleri anladığınızı düşünmeyin.

Çok soketli programlama (çoğunlukla sunucu programlama ile ilgilidir) açısından mevcut çözümlere genel bir bakış bulabileceğiniz başka bir kaynak bu sayfadır .


Oyun motoruma yeni başladım, bu yüzden yeniden yazmak sorun değil. Bu cevap gerçekten faydalı oldu ve kitap önerisi için teşekkür ederim. Oyunlarda ağ oluşturma hakkında daha spesifik bir kitap da biliyor musunuz?
Yannick Lange

3
@YannickLange: Hayır, ancak oyuna özgü kitaplar aramanızı tavsiye etmem, çünkü ağ iletişimi oldukça tür-agnostiktir ve ayrıca başka hiçbir kitap Stevens'ın kitabı seviyesine kadar değildir. Mesaj odaklı bir protokol kullanmak gibi UDP kullanmak için şeref, mesaj odaklı programlar (çoğu oyun gibi) yazarken iyi bir fikirdir. Birçok kişi TCP üzerinden bir mesaj soyutlaması yazmaya eğilimlidir, bu da kendi başına bir mesaj odaklı protokol (IP) üzerine inşa edilmiş bir akış yönelimli soyutlamadır.
Panda Pijama

-1

Hangi programlama dilini kullandığınızı yazmadınız, ancak çoğu dil, genellikle temel işletim sisteminin özelliklerini kullanan iyi asenkron soket çerçeveleri sağlar.

Engelleme soketlerine dayalı olarak kendi dişli uygulamanızı yazdığınızda (unutmayın: birden çok istemciniz olduğunda, her bir soket için bir iş parçacığına ihtiyacınız vardır), sadece eşzamansız soket çerçevesinin zaten ne sağladığını yeniden keşfedeceksiniz.

Bu yüzden asenkron prizler kullanmanızı tavsiye ederim.


4
neden her bir soket için bir dişe ihtiyacı var? Özellikle asenkron soketlerle mi? Birçok ağır sunucu, soket verilerini işlemek için bir "iş parçacığı havuzu" modeli kullanır; burada her iş parçacığı N istemcisine hizmet verir ve gerektiğinde üretilir veya öldürülür. Bu cevabın iyileştirilmesi gerektiğini düşünün: D
Grimshaw

@ Grimshaw Sanırım cevabımı yanlış anladın. Sanırım şimdi engelleme soketleri kullanılırken çok iş parçacıklı bir modelin gerekli olacağını açıkladım.
Philipp

@Philipp Hangi programlama dilini kullandığımı söylemedim, çünkü soru ile gerçekten ilgili olmadığını düşündüm (bu arada c ++ kullanıyorum). Zaman uyumsuz soket kullanma önerileriniz için teşekkür ederim. Oyunda (motorlarda) bu tür yöntemleri öğrenmek için önerilen bir kitap / web sayfası biliyor musunuz?
Yannick Lange

@Grimshaw: Her iş parçacığı Nistemcilere nasıl hizmet veriyor ? Engelliyorsanız ve soketlerin geri kalanının durumuna bakılmaksızın her soketin verilerini işlediğinden emin olmak istiyorsanız, soket başına bir iplik olması gerekir. Bunu engelleme soketleri kullanmayın.
Panda Pijama

Yorumum cevabınızın ilk versiyonuydu, bu arada, düzenlediniz ve düzelttiniz, söylediklerimi unutuyorsunuz: D
Grimshaw
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.