2010-12-16 15 views
5

Mam problemy z UdpClient w języku C#. Przesyłam strumieniowo dźwięk przez Internet między dwoma klientami.UdpClient - ograniczone buforowanie?

Na moim mikrofonie, z częstotliwością próbkowania 16 kHz, wysyłam pakiety UDP z dźwiękiem z 6400 bajtami na pakiet. Te nigdy się nie przedostają, z wyjątkiem ostatniego pakietu, który wynosi około 1200-3400, odkąd zamknę nagranie. Po obniżeniu częstotliwości próbkowania do 8 kHz wysyłam pakiety z 3200 bajtowym ładunkiem. Te zawsze przechodzą z jakiegoś powodu.

W zasadzie wszystko powyżej 3200 zostaje spartaczone (nie testowano dokładnej liczby, ale ...) dlaczego na tym polega? Myślałem, że wewnętrzny bufor UdpClient jest za mały czy coś w tym stylu? Ponieważ często przesyłam pakiety dźwiękowe.

otrzymują:

private void audioReceive(IAsyncResult asyn) 
    { 
     try 
     { 
      byte[] temp = audioSock.EndReceive(asyn, ref this.serverEP); 
      this.waveProvider.AddSamples(temp, 0, temp.Length); 

      this.textbox_display.Text = this.textbox_display.Text + " got bytes: " + temp.Length; 
      audioSock.BeginReceive(new AsyncCallback(audioReceive), null); 

     } 
     catch (Exception ez) 
     { 
      MessageBox.Show("audioReceive: " + this.textbox_nick.Text + "  " +ez.ToString()); 
     } 

    } 

nie mogę znaleźć żadnego oczywistego błędu. (Obiekt asyn dla funkcji ma wartość null btw, nie muszę używać obiektu stanu, ale nie powinien być z tym związany)

Wiem, że protokół UDP nie jest niezawodny, ale biorąc pod uwagę, że każdy pakiet o wielkości 3200 przechodzi przez i nie ma dla mnie rozmiaru 6400, szczególnie z maksymalnym rozmiarem, 64kb?

Wszelkie pomysły?

Odpowiedz

2

Możliwe jest odrzucenie pakietów przekraczających wartość MTU (która według mnie wynosi około 1500 bajtów). Na przykład see this. Wygląda na to, że możesz wpaść na jakąś formę tego. Aby umożliwić bardziej niezawodną pracę w różnych środowiskach, może być lepiej zmaksymalizować wysyłanie do 1472 bajtów na pakiet (aby umożliwić przesyłanie pakietów), a następnie złożyć je ponownie po stronie odbiorczej.

A może po prostu użyj protokołu TCP/IP. Nawet jeśli pewne straty są akceptowalne, może być dość skomplikowane wykonywanie "prostego" rozwiązania UDP. Pracuję nad produktem, który obsługuje komunikację dla UDP i TCP/IP, i (wykształcone odgadnięcie) implementacja UDP obejmuje prawdopodobnie 10 razy więcej kodu i ma znacznie większą złożoność. Oczywiście w naszej sytuacji żadna utrata danych nie jest akceptowalna, więc zmienia ją trochę.

+0

Z tym, że ten ruch przechodzi przez Internet, to brzmi jak to, co się dzieje. –

+0

Aby się rozwinąć, pakiety IP większe niż MTU będą pofragmentowane. Jeśli wszystkie fragmenty dotrą do miejsca docelowego, zostaną one ponownie złożone w oryginalnym pakiecie IP (zawierającym oryginalny datagram UDP) przez warstwę IP.Jeśli nie wszystkie pojawią się, nie ma mechanizmu w UDP, aby zażądać retransmisji, więc cały datagram zostanie utracony. – EJP

+0

Dziękuję, to jasne! – KaiserJohaan

0

Masz gwarancję 576 bajtów (548 na ładunek UDP) z IPv4, ale powinieneś sprawdzić, aby nie przekroczyć 1472 bajtów (1444 UDP) przynajmniej dla większości użytkowników.

Można sprawdzić, co działa wielkość MTU za pomocą polecenia ping, jak opisano tutaj,

http://help.expedient.net/broadband/mtu_ping_test.shtml

libjingle używa bezpiecznego domyślnego 1280 bajtów (1252 UDP/IPv4, 1232 UDP/IPv6), który jest zgodny z gwarantowaną minimalną IPv6,

http://code.google.com/p/libjingle/source/browse/branches/nextsnap/talk/session/tunnel/pseudotcpchannel.cc?spec=svn17&r=13