Ağ iletişiminde bayt sırasını güvenli bir şekilde yok sayabilir miyim?


24

İstemcinin Windows ve sunucu üzerinde muhtemelen Linux'ta çalışacağı bir sunucu-istemci uygulaması geliştiriyorum. Belki daha sonra istemciyi Mac ve Linux'a devrederim, ama henüz değil.

Bugünlerde tüm ev bilgisayarları küçük endian'larda çalışıyor. Bir süre googledim, ama büyük-endian'da çalışan cihazların listesini bulamadım. Bildiğim kadarıyla, bazı Motorola cipsleri hala büyük ve belki bazı telefonlar kullanıyor (uygulamayı akıllı telefonlara taşımayı planlamıyorum, bu yüzden bu benim için önemli değil). Öyleyse, neden her tamsayının baytını, her kısa, her kayan, iki katı vb. Yeniden düzenleyeyim, okuduğumda ve yazdığımda , hem sunucunun hem de müşterinin küçük-endian'da çalıştığını zaten bildiğim zaman ?

Bu sadece gereksiz işler yapmak için. Öyleyse benim sorum şu: Endian'ı güvenli bir şekilde görmezden gelebilir ve sadece küçük endian verilerini gönderebilir miyim? Dezavantajları nelerdir?


4
Makineler, normal / standart big-endian verileri yerine, az miktarda veri elde edip etmediklerini nasıl bilecek?
Ixrec,

2
Ağ protokolünün gerektirdiği meta verileri ve kodunuz dışındaki herkes için sadece bir kaç yorumlanmamış bayt yükünü ayırmanız gerekir. Umarım kendi ağ yığınınızı kullanmıyorsunuzdur. Sonuç olarak, sorunun yalnızca yük kapasitesiyle ilgili olduğunu düşünüyorum, doğru mu?

2
@delnan evet, sadece yük hakkında konuşuyor. Tabii ki ben hala ağ yığınının kendisine ağ bayt sırayla konuşacağım .
tkausl

3
Yan tarafta sadece bir düşünce: Doğaçlamanın bir endişe kaynağı olduğu bir soyutlama seviyesinde çalışmanız gerçekten gerekli mi? Tüm bu düşük seviyeli “karışıklığı” içine alan uygun kütüphanelerin bulunduğu protokolleri kullanmayı düşünmek faydalı olabilir. Ardından, daha fazla müşteri eklemenin çok daha kolay bir şekilde yapılabileceği konusunda ek bir bonusunuz var.
godfatherofpolka

1
@tkausl Tarafta sadece iki düşünce daha var: Genel bir kural olarak, IO hesaplamalar ile karşılaştırıldığında son derece yavaştır, bu nedenle daha yüksek bir soyutlama seviyesinde çalışarak ortaya çıkan herhangi bir ek yük büyük olasılıkla ihmal edilebilir düzeydedir. Bazı kütüphanelerin akıllı kaynak havuzu ve zaman uyumsuz kullanım vb. Nedenlerden dolayı elle yapılan uygulamalardan daha iyi performans gösterdiği bile olabilir. Bu yüzden, ilk önce mevcut çözümleri dikkatle değerlendiririm. Dahası, açıklamanız göz önüne alındığında, performanstan ziyade ölçeklenebilirlik üzerine bazı düşüncelerimi harcayacağım, burada daha yüksek seviyeli protokolleri kullanmaktan faydalanabilirsiniz.
godfatherofpolka

Yanıtlar:


29

... neden hem baytları yeniden düzenleyeyim ... hem de hem sunucunun hem de müşterinin küçük endian'da çalıştığını zaten bildiğimde? Bu sadece gereksiz işler yapmak için.

Kodunuzun daima küçük endian mimarilerinde çalışacağını garanti ederseniz, sadece gereksizdir. Uzun ömürlü olması niyetindeyseniz, büyük kanıtlanmış bir mimarinin “içinde” olduğu ve ondan iyi bir pazar olduğunu düşündüğünüz, on yıldan beri kanıtlanmış bir kodu rahatsız etmemek için ekstra bir çabaya değer başvurunuz.

Ağ standardı bir bayt siparişi var. Büyük-endian, ancak hiçbir şey protokolünüzü tasarlarken buna uymanız gerektiğini söylemez. Önceden vaktinizi biliyorsanız, kodunuzu çalıştıran sistemlerin çoğu küçük endian olacaktır ve performans önemlidir, "tkausl standart bayt siparişi" olduğunu beyan edin ve onunla devam edin. htons()İhtiyacınız olan şeyleri sıraya koymak için normalde arayacağınız yerde htots(), koşullu olarak küçük endian mimarilerinde hiçbir şey oluşturmayan ve büyük endian üzerinde yeniden düzenleme yapan bir makro yazın .

Gelen ve giden dönüşümleri yapmak için kodu korumak gerçekten büyük bir çaba değil. Çok sayıda mesajınız varsa, bunları ifade etmenin bir yolunu bulun ve gelen ve giden dönüşümleri oluşturmak için bir program yazın.


10
İfadeler when designing your protocolönemlidir, çünkü dolaylı olarak, bu seçeneğin sadece yeni bir protokol tasarlarken var olduğunu ve mevcut bazı protokolleri uygularken olmadığını söyler. Ve htots(ve tüm fonksiyonlar ailesinin gerçekte olan) ihtiyacından söz etmek , aynı zamanda farklı bir bayt sırası seçmenin birinin kodu daha basit hale getirmek için yaptığı bir şey olmadığını, ancak biraz daha hızlı hale getirebileceğini açıkça ortaya koyuyor.
kasperd

4
(Standart dışı ama çok yaygın bugünlerde) işlevleri vardır htole32(), htole16(), le16toh()sıra mevcut vb fonksiyonlar. Bunları bildirmek için eklenecek dosya ne yazık ki daha az standart: <endian.h>ya da <sys/types.h>platforma bağlı.
torek

Bu cevap gayet iyi, ancak bence performansın kritik olabileceği varsayımı, söz konusu durumun muhtemelen gerçeklerden ziyade batıl inançlara dayanarak yanlış bir varsayım olduğunu düşünüyorum.
Doktor Brown

1
@DocBrown: X protokolünün 30 yıl boyunca kendi bayt siparişinizi almayı desteklediğini ve o zamanki kaynakların olduğu kadar sıkı olduğunu, hiç kimsenin bir sorun olduğundan şikayet etmediğini belirtmek isterim.
Blrfl

7

Bu senin protokolün.

Güvenle görmezden gelemezsin. Ancak güvenli bir şekilde etiketleyebilirsiniz. İstemciyi ve sunucuyu kontrol edersiniz. Protokolü sen kontrol et. İki tarafın da aynı fikirde olup olmadığını bildiğiniz sürece, büyük ya da küçük endian olup olmadığını umursamak mantıklı değil mi?

Bu genel gider anlamına gelir. Şimdi endiannesini bir şekilde işaretlemelisin. Bunu yapın ve her şeyi okuyabilirim.

Eğer yükü yükseltmek istemiyorsanız ve CPU'nuz sıkılıyor ve yapacak bir şey arıyorsanız, o zaman uyun .


6

Öyleyse sorum şu: Ben soyağacını güvenli bir şekilde görmezden gelebilir ve sadece küçük endian verileri gönderebilir miyim?

Bunun iki yorumu var:

  • Uygulamalarınızı / protokollerinizi her zaman 1 küçük-endian gönderecek şekilde tasarlarsanız, o zaman kimseyi göz ardı edemezsiniz.

  • Uygulamalarınızı / protokollerinizi, yerel endiançinin ne olduğu gibi göndermek / almak üzere tasarlarsanız, uygulamalarınızı aynı yerel endiandıra sahip platformlarda çalıştırdığınız sürece çalışırlar.

    Bu "güvenli" 2 mi? Bu sizin yargılamanız içindir! Ama kesinlikle küçük-endian, büyük-endian veya ... bi-endian kullanan ortak donanım platformları var.

    Referans:

Dezavantajları nelerdir?

Endiandıyı gözardı etmenin açık bir dezavantajı, sizin / kullanıcılarınızın uygulamalarınızı / protokolünüzü farklı yerel endiansa sahip platformlar arasında çalıştırmanız gerekirse, o zaman bir sorununuz olur. Uygulamalar kopacak ve sorunu çözmek için bunları değiştirmeniz gerekecektir. Ve sürüm uyumluluğu sorunları, vb. İle ilgilenin.

Açıkçası, şu anki jenerasyon platformlarının çoğu doğal olarak küçük-endian, ancak 1) bazıları değil ve 2) yalnızca gelecekte neler olacağını tahmin edebiliriz.


1 - Her zaman ... doğal olarak büyük endian olan platformlar dahil.

2 - Gerçekten, "güvenli" ne anlama geliyor? Eğer donanım platformlarının gelecekteki yönünü tahmin etmemizi istiyorsanız ... Korkarım ki bu nesnel olarak cevapsız değil.


3

Endianness tek düşünce değil. Tam sayıların boyutu vardır, göndermek ya da almak isteyebileceğiniz yapıların paketleri vardır.

Tüm bunları görmezden gelebilirsiniz. Kimse seni zorlayamaz. Öte yandan, güvenli ve güvenilir bir yöntem, harici bir formatı belgelemek ve daha sonra, işlemciniz, programlama diliniz ve programlama dilinizin uygulaması ne olursa olsun, harici formatı doğru okuyacak veya yazacak bir kod yazmaktır.

Genellikle çok fazla kod yoktur. Ancak bunun çok büyük bir faydası var: Kodunuzu okuyan insanlar sizin ipuçsuz olduğunuzdan şüphelenmeyecek, dış verilerin değişimi hakkında hiçbir şey bilmeyecek ve genellikle güvenilmeyen bir kod yazacaklardır.


3

C'deki standart BSD ağ yığını, yerel ağ makinelerinde çalışmayanlara (big endian) yayılmayan hton/ ntohişlevselliğine ( network-to-host/ host-to-network) sahiptir. Ağa özgü bayt sırasının küçük endian olduğu senaryo için bunlara kendi meslektaşlarınıza ihtiyacınız olacaktır.

Bunu yapmanın sağlam yolu bu.

Sıradışı olurdu, ama yanlış bir şey göremiyorum. Ağa bağlı bilgisayarlar her zaman bytestest alırlar ve bu baytları nasıl yorumlayacakları konusunda protokoller üzerinde anlaşmaya ihtiyaçları vardır. Bu sadece bir parçası.


3

Sunucular arasında veri iletmek için kullanılan çeşitli protokoller küçük endian numaralarını kullanır:

  1. BSON
  2. Protokol Tamponları
  3. Capn Protokolü

Bazıları küçük harfli sayılara sahip, bazıları büyük harfli sayılara sahip çeşitli biçimlerdeki ayrıntılar için https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats adresine bakın .

Endian numaralarına dayanan bir protokol kullanmakta kesinlikle yanlış bir şey yoktur. Büyük bir endian makinesi, küçük endian sayılarını okuyabildiği kadar küçük endian sayılarını okuyabilir. Birçok kişi, küçük endian makinelerinde büyük-endian sayılarının kodunu çözmenin ekstra hesaplama maliyetinden kaçınmak için özellikle yaptı.

Protokolünüzü bu mevcut protokollerden birinin üzerine kurarsanız, o zaman zaten ilgilendiğiniz sorun hakkında endişelenmenize bile gerek yoktur. Kodunuzu büyük bir endian platformunda çalıştırmaya karar verdiğinizde, bu protokolleri uygulayan kütüphaneler, değerleri doğru bir şekilde çözdüğünüzden emin olmak için otomatik olarak ilgilenir.


2

Büyük bir endian sistemine bir örnek yönlendiricilerde kullanılan MIPS'dir. Hem ARM hem de MIPS endian-değiştirilebilirdir, ancak çoğu zaman MIPS büyük endian'dır çünkü ağ donanımını kolaylaştırır (bir kelimenin en önemli kısmı ilk aldığınız kısımdır ve geri kalanını almadan önce bir yönlendirme kararı verebilir) kelimeyi, tüm kelimeyi tamponlamak yerine,).

Bu nedenle, 'Linux' ile ne demek istediğinizi belirler, ancak sunucu uygulamanızı OpenWRT çalıştıran bir yönlendirici gibi daha küçük bir sistemde çalıştırmak istiyorsanız, büyük endian desteğini göz önünde bulundurmanız gerekebilir.

Her zaman olduğu gibi, varsayımları basitleştirmek, varsayımlara uymayan bir şeye çarpıncaya kadar tamamen mantıklı bir optimizasyondur. Ancak, böyle bir sorunla karşılaşırsanız, onları çözmenin ne kadar acı verici olduğunu söyleyebilirsiniz.


0

Cevapların hiçbiri yeterince kesin olduğunu sanmıyorum. Wikipedia'ya göre endianness, bir kelimeyi içeren baytların sırasıdır.

4 bayt alalım ve bunları int olarak yorumlayalım. Küçük bir endian sistemde, baytlar sağdan sola ve büyük bir endian sisteminde vertica olarak yorumlanacaktır. Açıkçası, bir int yorumlamak için hangi ucunda karar vermek önemlidir.

Json veya xml kullanıyor olabilecek modern ağ protokollerini biraz uzaklaştırmanızı sağlar. Bu formatların hiçbiri bir int'i 4 bayt olarak aktarmaz. Verileri, alıcı tarafta int olarak ayrıştırılacak metin olarak aktaracaklardır.

Sonunda endianness, json veya xml kullanılırken önemli değil. Tcp başlıkları için hala büyük endian kullanmamız gerekiyor, bu yüzden buna ağ bayt sırası deniyor, ancak çoğu programcının günlük olarak bunlarla uğraşması gerekmiyor.

Günümüzde en çok kullanılan kodlama, günümüzde endianness ile ilgili sorunlara karşı bağışıklık kazanmış olan utf-8'dir .

Bu yüzden evet derdim. Utf-8 kullanılarak aktarılan metin tabanlı formatları kullanırken dolandırıcılığı yoksaymak güvenlidir.


iki aşağı oy ve yorum yok. Harika.
Esben Skov Pedersen

1
Olumsuz olan kişi değildim ama bu cevap tamamen geçerli bir soruyu görmezden geliyor / reddediyor gibi görünüyor. Sadece bazı protokollerin metin tabanlı olması, tüm protokollerin olması gerektiği anlamına gelmez.
Peter Green

2
Yükseli yük formatının temel protokollerle hiçbir ilgisi olmadığı gerçeğine değdiği için bunu iptal ettim. Bazı insanlar sadece telafi problemlerine dalmayı sever.
Zdenek

0

Büyük endian sistemleri dışarı çıkıyor gibi görünüyor. Geleneksel unix'lerin çoğu büyük endian kullanıyordu, ancak yıllardır x86'daki linux lehine düşüş gösteriyorlar.

kol bi-endian ama büyük endian varyantı nadir görülüyor.

iki varyantta da dudaklar var. Büyük endian varyantı çoğunlukla ağ oluşturma uygulamalarında görülür (tarihsel nedenlerden ötürü internet protokolleri genellikle büyük endian kullanır).

ppc her iki kaygıyı da destekleyen bazı parçalarla geleneksel olarak büyük endian'dı ancak IBM şimdi 64-bit ppc için küçük endian modunu zorluyor gibi görünüyor (yakın zamanda ppc64el portlarını Debian ve Ubuntu'ya itti).

sparc normalde büyük endian olmakla birlikte yine düşüşe geçiyor gibi görünüyor.

Mevcut bir protokol uyguluyorsanız, belli ki şartnameye uymalısınız. IETF'in yeni protokolünüzü kutsamasını istiyorsanız, büyük endian'ın daha kolay olması muhtemeldir, çünkü mevcut protokollerinde zaten kullandıkları şey budur, ancak yeni bir "yeşil alan" protokolü tasarımı için IMO, küçük endian'ın yoludur.

Küçük endian sistemlerinde çalışmayan makroları baştan başlatabilir veya büyük bir endian sistemine geçmek zorunda olmadıkça / kullanana kadar rahatsız edemezsiniz.

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.