tags:

views:

302

answers:

1

Context: I'm porting a linux perl app to C#, the server listens on a udp port and maintains multiple concurrent dialogs with remote clients via a single udp socket. During testing, I send out high volumes of packets to the udp server, randomly restarting the clients to observe the server registering the new connections. The problem is this: when I kill a udp client, there may still be data on the server destined for that client. When the server tries to send this data, it gets an icmp "no service available" message back and consequently an exception occurs on the socket.

I cannot reuse this socket, when I try to associate a C# async handler with the socket, it complains about the exception, so I have to close and reopen the udp socket on the server port. Is this the only way around this problem?, surely there's some way of "fixing" the udp socket, as technically, UDP sockets shouldn't be aware of the status of a remote socket?

Any help or pointers would be much appreciated. Thanks.

+1  A: 

I think you are right in saying: 'the server should not be aware'. If you send an UDP packet to some IP/port which may or may not be open, there is no way of knowing for the server if it reached it's destination.

The only way for the server to know is to have the client send an ACK back. (Also both the client and server must have resend mechanisms in place in cases of lost packages).

So clearly something else is going on in your code (or with the .Net udp implementation)

EDIT:

After Nikolai's remark I checked the docs. And indeed there is a distinction in .Net to about being 'connected' or 'connectionless' when using UDP.

If you use code like this:

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);

then apparently you are 'connected'

However if you use code like this:

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

then you can send to whomever you choose without 'connecting'.

I'm not sure what your code looks like, but it might be worthwhile to check if you are using the correct set of commands which doesn't assume a 'connection'

Toad
Well, technically, the network stack is aware of a closed udp port if the remote end sends back an icmp "destination unreachable" signal, which some implementations do. Maybe I'll try blocking icmp temporarily and I'll see if I get the same exceptions...
Gearoid Murphy
@gearoid Even then, sending another package should work since the socket has no way of knowing if the port is back up or not
Toad
@reinier: there's a distinction between *connected* and *not-connected* UDP sockets. For the former, the kernel would know what application to direct that ICMP error to; for the latter it wouldn't, so the error is not delivered. It all boils down to socket port assignment. Then I have no idea how it works from .NET.
Nikolai N Fetissov
@reiner: thanks for the example code, I'll post more details when I know more....
Gearoid Murphy
In my code, the socket is a server socket, it's listening. The exception occurs during a recv op. To the best of my knowledge, the distinction between connected and connectionless udp sockets only arises in the context of the client.
Gearoid Murphy