2010-04-10 11 views
10

Kontekst: Przekazuję aplikację perl linux do C#, serwer nasłuchuje na porcie udp i utrzymuje wiele równoległych dialogów ze zdalnymi klientami za pośrednictwem pojedynczego gniazda udp. Podczas testowania wysyłam duże ilości pakietów do serwera udp, losowo restartując klientów, aby obserwować serwer rejestrujący nowe połączenia. Problem polega na tym, że gdy zabijam klienta udp, nadal mogą istnieć dane na serwerze przeznaczonym dla tego klienta. Gdy serwer spróbuje wysłać te dane, otrzyma komunikat "brak usługi", i w konsekwencji nastąpi wyjątek na gnieździe.Jak odzyskać wdzięk z wyjątku C# udp socket

Nie mogę ponownie użyć tego gniazda, gdy próbuję powiązać obsługę asynchronizmu C# z gniazdem, skarży się na wyjątek, więc muszę zamknąć i ponownie otworzyć gniazdo udp na porcie serwera. Czy to jedyny sposób obejścia tego problemu ?, z pewnością istnieje sposób "naprawienia" gniazda udp, ponieważ technicznie, gniazda UDP nie powinny być świadome stanu zdalnego gniazda?

Każda pomoc lub wskazówki byłyby mile widziane. Dzięki.

Odpowiedz

1

Myślę, że masz rację mówiąc: "serwer nie powinien być świadomy". Jeśli wyślesz pakiet UDP do jakiegoś adresu IP/portu, który może być otwarty lub nie, nie ma sposobu, aby dowiedzieć się, czy serwer osiągnął cel.

Jedynym sposobem, aby serwer się dowiedział, jest wysłanie przez klienta potwierdzenia ACK. (Także klient i serwer muszą mieć mechanizmy ponownego wysłania w przypadku utraty pakietów).

Tak wyraźnie coś innego dzieje się w kodzie (lub z .Net udp realizacji)

EDIT:

Po uwagą Mikołaja I sprawdzone docs. I rzeczywiście, w .Net istnieje rozróżnienie na temat bycia "połączonym" lub "bezpołączeniowym" podczas korzystania z UDP.

Jeśli używasz kodu:

UdpClient udpClient = new UdpClient(11000); //sourceport 
try{ 
    udpClient.Connect("www.contoso.com", 11000); //'connect' to destmachine and port 
    // Sends a message to the host to which you have connected. 
    Byte[] sendBytes = Encoding.ASCII.GetBytes("Is anybody there?"); 
    udpClient.Send(sendBytes, sendBytes.Length); 

potem widocznie jesteś „połączony”

Jednak jeśli użyć kodu jak poniżej:

 UdpClient udpClientB = new UdpClient(); 
    udpClientB.Send(sendBytes, sendBytes.Length, "AlternateHostMachineName", 11000); 

następnie można przesłać do kogokolwiek wybierzesz bez "łączenia".

Nie jestem pewien, co Twój kod wygląda, ale może warto byłoby sprawdzić, czy używasz właściwego zestawu poleceń, które nie zakładają „połączenie”

+1

dobrze, technicznie, stos sieciowy jest świadomy zamkniętego portu udp, jeśli zdalny koniec odsyła sygnał "docelowy nieosiągalny" icmp, co robią niektóre implementacje. Może spróbuję tymczasowo zablokować program icmp i zobaczę, czy dostaję te same wyjątki ... –

+0

@gearoid Nawet wtedy wysyłanie innego pakietu powinno działać, ponieważ gniazdo nie ma możliwości sprawdzenia, czy port jest z powrotem podłączony, czy nie – Toad

+1

istnieje rozróżnienie między * podłączonymi * i * niepołączonymi * gniazdami UDP. W przypadku pierwszego z nich jądro wie, do której aplikacji należy kierować ten błąd ICMP; w drugim przypadku nie, więc błąd nie zostanie dostarczony. Wszystko sprowadza się do przypisania portu gniazda. Wtedy nie mam pojęcia, jak to działa z .NET. –

Powiązane problemy