Question about UdpClient

G

Guest

I have the following program


using System;
using System.Collections;
using System.Net.Sockets;
using System.Net;
using System.IO;
public class Test {
public static void Main(string[] s) {
byte[] data;
data = new byte[512];
try
{
UdpClient dnsClient = new UdpClient("192.168.1.9", 100);
//send the data packet
dnsClient.Send(data,data.Length);
IPEndPoint endpoint = null;
//receive the data packet from DNS server
data = dnsClient.Receive(ref endpoint);
}
catch (Exception e )
{
Console.WriteLine(e.ToString());
}
Console.ReadLine ();
}
}

This program is compiled with a c# console app and startup class changed to
Test

My question is about the UdpClient; since the methods do not return status
values (success or fail) we need to use try/catch, is this correct?

Now,
I am trying to connect to a host "192.168.1.9", which doesn't exist, so I
expect to receive a time-out exception, however, this is not the case.
The call simply waits about 20 seconds, then goes on to the sending
method, which return immediately without any exception printed on the
console. The, when the receiving function is called, the program simply
block foreever, obviously, since there is no such host anyway.
Basically, why doesn't UdpClient throw exceptions?
Thanks.
 
P

Peter Duniho

Smuggy said:
[...]
My question is about the UdpClient; since the methods do not return status
values (success or fail) we need to use try/catch, is this correct?

Yes. The Socket class methods have overloads that include an "out"
error parameter, but UdpClient() doesn't so you have to catch exceptions
to detect the errors.
Now,
I am trying to connect to a host "192.168.1.9", which doesn't exist, so I
expect to receive a time-out exception, however, this is not the case.
The call simply waits about 20 seconds, then goes on to the sending
method, which return immediately without any exception printed on the
console.

UDP is a connectionless protocol. The call to the UdpClient()
constructor might take 20 seconds, but it shouldn't be making any
attempt to connect to anything. There's nothing for it to connect to.
All that supplying a remote address and port does is preconfigure the
UdpClient so that you don't have to provide the address each time you
want to send data.

It surprises me that it takes 20 seconds for the constructor to return,
but maybe there's some sort of initialization that takes time (loading
an assembly, or enumerating network protocols, or something like that).

To reiterate: even when you specify a remote address in the UdpClient()
constructor, that does not create a connection. The UdpClient() can
still send to and receive from other remote addresses. All you're doing
is specifying the default address to use for sending.
The, when the receiving function is called, the program simply
block foreever, obviously, since there is no such host anyway.
Basically, why doesn't UdpClient throw exceptions?

Because that's how UDP works. Any address you give to a UDP method is
used only for sending, and only if you actually send something. For
receiving, the UDP port will receive data from any remote endpoint that
sends a datagram to the correct address and port, and it is not an error
for no data to be sent even if you've called Receive().

Pete
 
G

Guest

Yes. The Socket class methods have overloads that include an "out"
error parameter, but UdpClient() doesn't so you have to catch exceptions
to detect the errors.


UDP is a connectionless protocol. The call to the UdpClient()
constructor might take 20 seconds, but it shouldn't be making any
attempt to connect to anything. There's nothing for it to connect to.
All that supplying a remote address and port does is preconfigure the
UdpClient so that you don't have to provide the address each time you
want to send data.

It surprises me that it takes 20 seconds for the constructor to return,
but maybe there's some sort of initialization that takes time (loading
an assembly, or enumerating network protocols, or something like that).

To reiterate: even when you specify a remote address in the UdpClient()
constructor, that does not create a connection. The UdpClient() can
still send to and receive from other remote addresses. All you're doing
is specifying the default address to use for sending.


Because that's how UDP works. Any address you give to a UDP method is
used only for sending, and only if you actually send something. For
receiving, the UDP port will receive data from any remote endpoint that
sends a datagram to the correct address and port, and it is not an error
for no data to be sent even if you've called Receive().


What you say does make sense, however there is one thing which
is puzzling:
I now changed the host to "192.168.1.1" which I know for a fact
does exist, it is my router gateway. When I did that, the constructor
method returned immediately without waiting 20 seconds.
 
P

Peter Duniho

Smuggy said:
What you say does make sense, however there is one thing which
is puzzling:
I now changed the host to "192.168.1.1" which I know for a fact
does exist, it is my router gateway. When I did that, the constructor
method returned immediately without waiting 20 seconds.

Yes, that's puzzling. I don't know what UdpClient might be doing there;
you might want to use the Reflector tool to see if you can inspect its
implementation and find out. Or use a network sniffing utility like
Ethereal to watch what happens on the network in each case, in case you
think it's actually sending some data.

Whatever the case, I'm reasonably confident that the UdpClient is not
actually sending anything to the remote endpoint. Unlike TCP, UDP
doesn't have any sort of connection-creating handshake underlying the
protocol. If a datagram is sent from one end, it's received at the
other end (notwithstanding the unreliable nature of UDP, of course). It
would be a bad idea to be sending random datagrams just to test the
network path, since the other end would have no way to know how to
interpret such a datagram.

The bottom line here is that calling UdpClient.Receive() isn't going to
create an exception just because the remote endpoint you bound in the
constructor doesn't exist, and that's by design.

Pete
 
C

Chris Shepherd

Peter said:
Yes, that's puzzling. I don't know what UdpClient might be doing there;
you might want to use the Reflector tool to see if you can inspect its
implementation and find out. Or use a network sniffing utility like
Ethereal to watch what happens on the network in each case, in case you
think it's actually sending some data.

It's probably doing ARP resolution to determine the ethernet address
that 192.168.1.9 belongs to since it's on your network. It won't get a
response inside of its timeout window, but will wait the full timeout
window anyways, which explains the delay. If this is indeed what it is
doing, then wen you use an existing host, it will send out the ARP
request and it should get a quick response OR -- and far more likely
since you indicated it's your router/gateway -- is that it already has
the IP -> MAC mapping stored in the ARP cache. On XP you can watch this
via arp -a from a command line.

Using Ethereal as suggested will confirm whether or not this is the
case, but it's my best guess.

Chris.
 
G

Guest

Just installed ethereal. It is all wrong, UdpClient does send a packet
from the constructor.

I think I found out my problem. It looks as though my new D-Link
router does not relay dns mx queries. I clearly remember my program
worked before when I had my old Belkin router. Has anyone got
the DLINK DSL-G624T ?
 
P

Peter Duniho

Smuggy said:
Just installed ethereal. It is all wrong, UdpClient does send a packet
from the constructor.

What is all wrong? Neither I nor Chris suggested that no data would be
sent in the constructor. Simply that no datagram would be sent to the
remote endpoint you specify in the constructor.

Are you saying that Ethereal is reporting a datagram that is sent to
192.168.1.9:100? That would be incorrect behavior.
I think I found out my problem. It looks as though my new D-Link
router does not relay dns mx queries. I clearly remember my program
worked before when I had my old Belkin router. Has anyone got
the DLINK DSL-G624T ?

What problem? You haven't posted a description of something that's a
problem. Are you still concerned about the lack of an error calling
Receive()?

If you have code that used to report an error when you call Receive() on
a UdpClient or UDP Socket, then the _error_ was the problem. It is
correct behavior for a blocking receive on a UDP port, whether via
UdpClient or a UDP Socket, to simply block indefinitely until data has
been received. The endpoint passed to the constructor should be
irrelevant, and if it's not, then _that_ is a bug.

Pete
 
G

Guest

What is all wrong? Neither I nor Chris suggested that no data would be
sent in the constructor. Simply that no datagram would be sent to the
remote endpoint you specify in the constructor.

Are you saying that Ethereal is reporting a datagram that is sent to
192.168.1.9:100? That would be incorrect behavior.


What problem? You haven't posted a description of something that's a
problem. Are you still concerned about the lack of an error calling
Receive()?

If you have code that used to report an error when you call Receive() on
a UdpClient or UDP Socket, then the _error_ was the problem. It is
correct behavior for a blocking receive on a UDP port, whether via
UdpClient or a UDP Socket, to simply block indefinitely until data has
been received. The endpoint passed to the constructor should be
irrelevant, and if it's not, then _that_ is a bug.

I have a problem with a similar program, so I started debugging and run
into this stange UdpClient behaviour (well, it's not really strange)

The main problem, which is why I started debugging, is that I think my
new router does not work well with email dns queries (mx). This is
required for running an smtp server.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top