2011-08-24 18 views
6

Şu anda yazdığım bir yönetilen C# ağ kitaplığını test ediyorum ve ara sıra bir soruna karşı geliyorum. Bu sorun, tüm gönderme işlemlerinin belki% 1'i için networkstream.write() üzerinde çok tutarlı (her zaman 30ms içinde) 5000ms'lik blok olarak ortaya çıkar. Bu, her seferinde tam olarak aynı paket boyutunu (2MB) kullanarak, yerel olarak çalışan bir test ortamındadır.Networkstream.Write() Engelleme Sorunu

tcpClientNetworkStream.Write(headerBytes, 0, headerBytes.Length); 
tcpClientNetworkStream.Write(dataBytes, 0, dataBytes.Length); 

ve sunucu ucunda ben uyumsuz bir veri bekleniyor okumak kullanın: istemci ucunda ben sürekli bağlı bir NetworkStream için aşağıdaki yazın. Veri göründüğünde, tüm veriler alınana kadar tcpClientNetworkStream.DataAvailable üzerinden bir while döngüsü kullanıyorum.

Ben tamponlar dolu ama bu sunucu sonunda onları temizleyerek daha hızlı bir şekilde düşünemiyorum sorunudur if (gönderme ve tampon boyutları varsayılan olan al eğer networkstream.write() engelleyebilirsiniz farkındayım 8192 bayt. Bloğun o kadar tutarlı olduğu gerçeği çok garip görünüyor. İlk düşüncem muhtemelen bir çeşit Thread.Sleep idi ama tam bir proje araştırması hiç göstermiyor. Eğer herkes bu konuda biraz ışık tutabilirse, bu konuda çok takdir edilecek.

Marc eklemek için

düzenleme: problemi ortadan görünüyor Bir kesmek şudur (BlockCopy nedeniyle hit ilişkili bir performans olmamasına rağmen): Add2 için

byte[] bytesToSend = new byte[headerBytes.Length + dataBytes.Length]; 
Buffer.BlockCopy(headerBytes, 0, bytesToSend, 0, headerBytes.Length); 
Buffer.BlockCopy(dataBytes, 0, bytesToSend, headerBytes.Length, dataBytes.Length); 
tcpClientNetworkStream.Write(bytesToSend, 0, bytesToSend.Length); 

düzenlemek : Ayrıca, iki arasında bir iş parçacığı sinyali ile iki eşzamansız yazarak sorunu yeniden ürettim. Şu anda sahip olduğum tek çözüm, yukarıdaki düzenlemede olduğu gibi tek yazma işlemidir.

add3'e ekle: Tamam, başka bir olası düzeltme izler. Hala neden ardışık yazma, neden olduğu gibi 'blok' neden bilmek istiyorum. add4 için

BufferedStream sendStream = new BufferedStream(tcpClientNetworkStream); 
sendStream.Write(bytesToSend, 0, bytesToSend.Length); 
sendStream.Write(packet.PacketData, 0, packet.PacketData.Length); 
sendStream.Flush(); 

düzenleme: problemi ortadan yapmaz 'Add3 için düzenlemek' çözümü test ayrıca kapsamlı, sadece yaklaşık% 0.1'e çıkmasını azaltan sonra bir gönderir. Çok daha iyi ama çözülmekten uzak. Eşzamansız okumayı, PaulF tarafından önerilen şekilde sıralayıp sıralamayacağınızı görmek için bir engelleme okumasıyla değiştireceğim.

+0

Daha fazla kod gönderiniz, dataBytes nereden geliyor? Bir yerlerde tamponlanmış mı? – EKS

+0

Bir paket nesnesini, yukarıdaki NetworkStream.Write() yöntemlerini içeren bir SendPacket() yöntemine iletirim. Bu paket nesnesi SendPacket() dışında oluşturulduğunda, hem 'headerBytes' hem de 'dataBytes' için byte dizileri içerir. – MarcF

+0

Sunucu tarafında senkronize (engelleme) okumaları kullanırsanız sorunun devam edip etmediğini merak ediyorum. – PaulF

cevap

2

Tamam, bu soruya verilen belirli bir cevap yok, bu yüzden kendime küçük bir sonuç vermek için elimden gelenin en iyisini yapacağım. En iyi tahminim, bu sorunun asıl nedeni, tcp arabellekini temizlediğimden daha hızlı doldurduğumdan kaynaklanmış olmasıdır. Arabellek doluysa, daha fazla veri eklemeden önce bilinmeyen bir bekleme süresi vardır. Bu problem, aynı makine içerisinde veri gönderip alırken belki de en belirgin olacaktır. .net'deki varsayılan okuma arabelleği boyutunun yalnızca 8192 bayt olduğunu hatırlamak önemlidir, bu nedenle çok daha büyük parçalarda yazıyorsa, bu okuma arabelleği boyutunu 512000 bayt gibi daha büyük bir boyuta yükseltmeyi düşünebilirsiniz. Ancak bu, kendi içinde büyük nesne yığını vb. Nedenlerle başka sorunlara neden olur, ancak bu potansiyel olarak farklı bir soruyu tartışır.