TCP ve UDP paketleri parçalara ayrılabilir mi?


41

TCP paketleri alıcıya parçalar halinde ulaşabilir mi?

Örneğin, TCP protokolünü kullanarak 20 bayt gönderirsem, bir kerede tam olarak 20 bayt alacağımdan,% 10 bayttan sonra 10 bayt alacağımdan% 100 emin olabilir miyim?

UDP protokolü için de aynı soru.
UDP'nin güvenilmez olduğunu ve paketlerin hiçbir şekilde ulaşamayacağını veya farklı sırada gelemeyeceğini biliyorum, peki ya tek bir paket? Gelirse, bir parça değil, eksiksiz bir paket olduğundan emin olabilir miyim?


7
Açıklığa kavuşturma noktası: Buna TCP kesimi ve UDP datagramı denir. Paket değiller. TCP = Segment, UDP = Datagram, IP = Paket, Ethernet = Çerçeve, Diğer tüm katmanlarda (AFAIK), sadece PDU'lar (Protokol Veri Birimleri) olarak adlandırılır.
joeqwerty

Yanıtlar:


33

TCP paketleri alıcıya parçalar halinde ulaşabilir mi?

Evet. IP genellikle parçalanmayı destekler, ancak TCP genellikle MTU yolunu belirlemeye ve paketlerini performans nedenleriyle olduğundan daha küçük tutmaya çalışır. Parçalanma, datagram kayıp oranını felaketle arttırır. Bir yol% 10'luk bir paket kaybı oranına sahipse, bir datagramı iki pakete ayırmak, veri birimi kayıp oranını neredeyse% 20 yapar. (Paketlerden herhangi biri kaybolursa, datagram kaybolur.)

Bu konuda endişelenmenize gerek yok ve TCP katmanı da yok. IP katmanı, paketleri tüm datagramlara yeniden birleştirir.

Örn: TCP protokolünü kullanarak 20 byte gönderirsem, bir kerede tam olarak 20 byte alacağımdan,% 10 byte alacağımdan% 100 emin olabilir miyim?

Hayır, ama bunun paketlerle ilgisi yok. TCP, temel olarak, uygulama mesajı sınırlarını korumayan bir bayt akış protokolüdür.

UDP protokolü için de aynı soru. UDP'nin güvenilmez olduğunu ve paketlerin hiçbir şekilde ulaşamayacağını veya farklı sırada gelemediğini biliyorum.

Aynısı TCP için de geçerlidir. Paketler paketlerdir. Aradaki fark, TCP'nin UDP olmasa da protokolde yerleşik olarak yeniden denemeleri ve yeniden düzenlemeleri olmasıdır.

peki ya 1 paket? Gelirse, bir parça değil, eksiksiz bir paket olduğundan emin olabilir miyim?

Hayır, ama bu senin sorunun değil. UDP protokolü datagram montajını gerçekleştirir. Bu işinin bir parçası. (Gerçekte, IP protokolü bunu UDP protokolü için yapar, bu yüzden UDP bunu yalnızca IP'nin üstüne yerleştirerek yapar.) Bir datagram iki pakete bölünürse, IP protokolü UDP protokolü için yeniden birleştirir. tüm verileri göreceksiniz.


10
Acemi okuyucular için son ucu açıklığa kavuşturmaya değer olabilir: söz konusu datagram için tam verileri göreceksiniz . Bölünmüş paketlerden herhangi biri kaybolursa, datagram kaybolur ve UDP katmanı bunu asla bilemez. Datagramdaki bütün paketler alındığı sürece, bunlar IP katmanında toplanacak ve daha sonra UDP katmanına geçirilecektir. Bu, veri akışında "parçaların" bulunma olasılığını engellemez. Pedant olmak değil, ama bu şeyleri öğrenirken, 2. veya 3. ders kitabından geçinceye kadar IP fragmanı ve UDP kaybı arasındaki farkı kırmadım.
Justin,

20

Fiziksel olarak aynı anda geldiklerinden emin olamazsın. TCP / UDP'nin altındaki Veri bağlantısı katmanları, isterlerse paketinizi bölebilir. Özellikle internet üzerinden veya kontrolünüz dışındaki herhangi bir ağ üzerinden veri gönderirseniz, bunu tahmin etmek zordur.

Ancak, verinin alıcıdaki bir pakete veya birden fazla pakete ulaşması farketmez. İşletim sistemi bu paketlerin birleşimini soyutlamalıdır, bu nedenle uygulamanız için hala her şey bir anda gelmiş gibi görünmektedir. Bu nedenle, bir çekirdek korsanı değilseniz, çoğu durumda bu verilerin bir veya daha fazla pakette aktarılması durumunda endişelenmenize gerek yoktur.

UDP için, işletim sistemi de bazı soyutlamalar yapacaktır; bu nedenle, verileri alan uygulamanın, verilerin kaç paket iletildiğini bilmesi gerekmez. Ancak TCP'ye olan fark, verinin gerçekten ulaşması için bir garanti olmadığıdır. Verilerin birden fazla pakete bölünmesi de mümkündür, bazıları gelip bazıları gelmez. Alıcı uygulama için, tamamlanmış olsun veya olmasın, yine de bir veri akışı gibi görünür.


Ağ kartı sürücüsü, çekirdeklerin değil paketlerin yeniden birleştirilmesiyle ilgilenmiyor mu?
bluehallu

2
@Halucynogenyc: İşler değişmediği sürece, Internet protokolü 576 bayttan daha büyük paketlerin yolculuklarında herhangi bir noktada bölünmelerine izin vermek üzere tasarlanmıştır, ancak nihai alıcıdan başka bir şeyin onları yeniden birleştirmesini beklememektedir. Bence fikir, daha büyük paketlerin kullanılmasının çoğu durumda ek yükü azaltma çabası olduğunu düşünüyorum; Bir paket yolculuğunun bir noktasında bölündüğünde, ek yük zaten gerçekleşti, bu yüzden son alıcı hiçbir şey için uygun olmadığından ve yeniden bölünmesi gerekiyorsa zarar verebilir.
Supercat,

576 bayttan daha büyük olan herhangi bir paket bölünebilirken, bu boyutun altındaki paketlerin değişmeyebileceğine inanıyorum; Bölünmüş paketlerle ilgilenemeyen gömülü sistemler bundan daha büyük bir şey istemekten kaçınmalıdır.
Supercat,

1
@ mauro.stettler: "Çıplak metal" üzerine bir TCP yığını yazdım (doğrudan bir dizi ağ arayüzü yongasıyla konuşmak için kodu yazıyorum). 576 bayt sınırına sahip bir bağlantıyla daha uzun paketleri bölmek için konuşan donanım için basittir. Paketlerin yeniden montajı çok daha karmaşıktır, özellikle de biri tam olarak alınmadan önce birçok farklı paketin parçalarını alabilir.
supercat

Bunun için bölünmüş olmayacağını biraz ümit var küçücük her birinin istenen bir "garantili maksimum boyut" olduğundan yükleri (yaklaşık 10 veya 20 bayt ok olmalıdır), hop , en az 68 bayt (dahil: ipv4 IP, Paketler için IP başlıkları ve alt düzey başlıkları saymıyor). en.wikipedia.org/wiki/Maximum_transmission_unit sayfasındaki 1. tabloya bakınız . HOSTS'tan istenen asgari büyüklükteki 576 bayttan farklıdır (yani, tüm ara atlama noktalarının değil, iletimin başlangıcı veya sonu). Dikkatli olun: taşıma yükü daha düşüktür (her bir katmanın başlığı biraz yer kapladığından).
Olivier Dulac

14

Örnekler. Bitişik karakter blokları send () çağrılarına karşılık gelir:

TCP:

Send: AA BBBB CCC DDDDDD E         Recv: A ABB B BCC CDDD DDDE

Gönderilen tüm veriler sırayla alınır, ancak aynı parçalarda olması gerekmez.

UDP:

Send: AA BBBB CCC DDDDDD E         Recv: CCC AA E

Verilerin mutlaka aynı sırada olması gerekmez ve mutlaka alınması gerekmez, ancak mesajların tümü korunur.


5

Örn: TCP protokolünü kullanarak 20 byte gönderirsem, bir kerede tam olarak 20 byte alacağımdan,% 10 byte alacağımdan% 100 emin olabilir miyim?

Hayır, TCP bir akış protokolüdür, verileri düzenli tutar ancak mesajla gruplamaz. Öte yandan UDP mesaj odaklı, ancak güvenilmez. SCTP , her iki dünyanın da en iyisine sahiptir, ancak doğal olarak kullanılamaz, çünkü NAT'ler interneti bozar.


1

Bir TCP akışının en başında 20 bayt gönderirseniz, iki 10 baytlık parça gelmeyeceğine dair bazı güvenceler vardır. Bunun nedeni, TCP yığınının bu kadar küçük kesimleri göndermemesidir: Asgari bir MTU boyutu vardır. Ancak, eğer gönderme bir akışın ortasında herhangi bir yerdeyse, tüm bahisler kapalıdır. Protokol yığınızın bir bölümü doldurup göndermek için 10 bayt veri alıyor olabilir ve ardından on bayt başka bir bölüme gider.

Protokol yığınız verileri parçalara ayırır ve sıraya yerleştirir. Öbek boyutlar MTU yolunu temel alır. Bir gönderme işlemi gerçekleştirirseniz ve hala bekleyen kuyruğa alınmış veriler varsa, protokol yığını genellikle kuyruğun kuyruğundaki segmente göz atar ve bu segmentte daha fazla veri eklemek için yer olup olmadığını görür. Oda bir bayt kadar küçük olabilir, bu nedenle iki baytlık bir gönderme bile ikiye ayrılabilir.

Diğer taraftan, verilerin bölümlenmesi, kısmi okumaların olabileceği anlamına gelir. Bir alma işlemi, bir bölümden az sayıda ürün geldiğinde potansiyel olarak uyanabilir ve veri alabilir. Yaygın olarak uygulanan soketler API'sinde bir alma çağrısı 20 bayt isteyebilir, ancak 10 ile geri dönebilir. Elbette, üzerine 20 bayt alınana veya bağlantı kopuncaya kadar bloke edecek bir tamponlama katmanı oluşturulabilir. POSIX dünyasında, bu API standart I / O akışları olabilir: fdopenbir FILE *akış elde etmek için soket tanımlayıcısını kullanabilir freadve tam isteğin gereken sayıda readçağrıdan memnun olacağı bir arabellek doldurmak için kullanabilirsiniz . .

UDP datagramları verileri çerçeveler. Her gönderim çağrısı bir datagram oluşturur (ancak aşağı yukarı corking hakkında bakın). Diğer taraf tam bir datagram alır (ve soket API'sinde, onu tutacak kadar büyük bir tampon belirtmelidir, aksi takdirde datagram kesilecektir). Büyük datagramlar IP parçalanması ile parçalanır ve uygulamalara şeffaf bir şekilde yeniden monte edilir. Herhangi bir parça eksikse, tüm datagram kaybolur; Bu durumda kısmi verileri okumak için bir yol yoktur.

Tek bir datagram belirtmek için çoklu işlemlere izin veren arayüzde uzantılar vardır. Linux'ta bir soket "cork" edilebilir (gönderilmesi engellenebilir). Mantarlanırken, yazılı veriler tek bir ünitede toplanır. Ardından soket "kayıtsız" olduğunda, tek bir datagram gönderilebilir.


bu yanlıştır: eğer biri 10 veya 20 baytlık bir taşıma yüküne sahip bir paquet gönderirse, bu 1 paquet üretecektir ve (yukarıda söylediğim gibi), eğer ipv4 kullanıyorsanız, diğer protokol katmanlarının tüm başlıklarını eklerken bile 68 bayt içerisine girer, bu sayede tüm paketlerden 1 paket içinde geçmesini sağlar. Tcp yığını (1. paragrafınızda belirtildiği gibi) "mtu dolana kadar bekleyin (yani uygun boyutta bir tane yapmak için birkaç paket ekleyin)" bir paket göndermek için! ... Bu davranış birçok şeyi bozar ( bu "fragmanlar", aynı ana bilgisayar çiftine gönderilirse bile)
Olivier Dulac

@OlivierDulac: Bu yanlış. TCP genellikle ağ kullanımını optimize etmeye çalışan paketler üretir, böylece 20 bayt, Kaz tarafından açıklandığı gibi iki farklı pakette sonuçlanabilir. Bu, uygulamanızın daha hızlı TCP ağı gerektirmesi durumunda, baytları paketlere gönderen Nagles algoritmasını devre dışı bırakan TCP_NODELAY soket seçeneği kullanılarak kontrol edilebilir . Ayrıca, 68 bayt paket uzunluğu için fiili standart değildir. 1500 bayt daha normal bir değerdir (bu gerçekten ağlar arasında değişir).
jjmontes
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.