Main Site Documentation

UDP message problem


#1

I got a problem with receiving some UDP communication using a Domino and the W5100 ethernet board. I’ve been using the example at http://www.tinyclr.com/downloads/Shield/Broch_EthernatShield.pdf as a start.

I’ve changed the code so it worked at my network and ended up with the code below for my Domino. To test the Domino there is a small WinForm application, sending a UDP message. To recreate the WinForm application drag a button on a form and call the SendUdpMessage sub when clicking on the button.

The problems are at the lines with remoteEndPoint. An endpoint with the port != 0 will work. Normally port 0 is used to specify any port, but there is nothing received anymore? What do I miss?

WinForm Application


public void SendUdpMessage()
{
	System.Net.Sockets.UdpClient socket = new System.Net.Sockets.UdpClient();
	byte[] msg = System.Text.Encoding.UTF8.GetBytes("TestMessage");
	IPEndPoint EndPoint = new IPEndPoint(IPAddress.Parse("10.0.64.188"), 2000);
	socket.Send(msg, msg.Length, EndPoint);
}


using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Net;
using GHIElectronics.NETMF.Net.Sockets;
using GHIElectronics.NETMF.Net.NetworkInformation;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System;
using System.Text;

Namespace MyNamespace
{
    public class Program
    {
        private static void Main()
        {
            byte[] ip = { 10, 0, 64, 188 };
            byte[] subnet = { 255, 255, 255, 0 };
            byte[] gateway = { 10, 0, 64, 254 };
            byte[] mac = { 42, 173, 190, 239, 254, 237 };

            WIZnet_W5100.Enable(SPI.SPI_module.SPI1,
                        (Cpu.Pin)FEZ_Pin.Digital.Di10,
                        (Cpu.Pin)FEZ_Pin.Digital.Di9, true);

            NetworkInterface.EnableStaticIP(ip, subnet, gateway, mac);
            NetworkInterface.EnableStaticDns(new byte[] { 10, 0, 64, 254 });

            Socket serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            //EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse("10.0.64.72"), 2000);      // works
            //EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 2000);                    // works
            EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse("10.0.64.72"), 0);       // fails
            //EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);                       // fails

            serversocket.Bind(remoteEndPoint);

            while (true)
            {
                if (serversocket.Poll(-1, SelectMode.SelectRead))
                {
                    byte[] inBuf = new byte[serversocket.Available];
                    int count = serversocket.ReceiveFrom(inBuf, ref remoteEndPoint);
                    Debug.Print(new String(Encoding.UTF8.GetChars(inBuf)));
                }
            }

        }
    }
}


#2

Bind binds a socket to a LOCAL interface and port. Not the remote host that is sending you a message.

Binding to port zero is not valid.

The correct EndPoint to use is:

EndPoint /*remoteEndPoint*/ localEP = new IPEndPoint(IPAddress.Any, 2000);

#3

I agree the name of the endpoint variable is not a very logical one, but it was copied from the example. In the end it will not break the code.

The documentation for the IPEndPoint documentation says port 0 can be used, although I don’t understand the note about the host order.

http://www.ghielectronics.com/downloads/NETMF/Library%20Documentation/html/f76b8335-41d8-d46c-b14b-1bad93791ddc.htm
[italic]port
Type: System…::…Int32
The port number associated with a specific IP address, or 0 (zero) to specify any available port. Note that the port parameter value is in host order.
[/italic]
The idea is to communicate with a service that sends a reply to a UDP port > 1023 on the Domino, but the exact port is random.


#4

if a udp packet is being sent to port 2000 then the receiver must bind to port 2000 ot it will not work, as you
stated.

this is not the place to use an endpoint with a zero port.


#5

Mike is correct.
I don’t think you can bind to port zero, let me double check. Just keep the socket unbound if you want it to receive from any port.

There is another thing I want to pay your attention too in the following

 int count = serversocket.ReceiveFrom(inBuf, ref remoteEndPoint);

ReceiveFrom() method will record the endpoint that sent the data in remoteEndPoint.
So by checking the IP address of the resulting remoteEndPoint you will be able to identify who sent the message.


#6

Binding to zero port = Not binding to port.


#7

[quote]Binding to zero port = Not binding to port.
[/quote]

The only use for binding to port zero would be on a machine with multiple ip interfaces. Would use to bind a TCP socket to a specific interface before doing a connect.


#8

I expected setting the port to 0 would mean traffic from all ports was accepted. Just the way IPAddress.Any means from all addresses.

Not binding the port sounds good, but I can’t get it to work.

Documentation is also contradicting,
http://msdn.microsoft.com/en-us/library/wdfskwcy.aspx states
[italic]Before calling ReceiveFrom, you must explicitly bind the Socket to a local endpoint using the Bind method. If you do not, ReceiveFrom will throw a SocketException.[/italic]
Above is for .NET BIG Framework, and probably not for Micro.

The current code is below.
Uncommenting the two lines with localEndPoint and the program works.
Commenting those two lines and the program does not receive anything.

I would like to see all incoming UDP messages from all IP addresses at all ports.

    
    public class Program
    {
        private static void Main()
        {
            byte[] ip = { 10, 0, 64, 188 };
            byte[] subnet = { 255, 255, 255, 0 };
            byte[] gateway = { 10, 0, 64, 254 };
            byte[] mac = { 40, 173, 190, 239, 254, 237 };

            WIZnet_W5100.Enable(SPI.SPI_module.SPI1,
                        (Cpu.Pin)FEZ_Pin.Digital.Di10,
                        (Cpu.Pin)FEZ_Pin.Digital.Di9, true);

            NetworkInterface.EnableStaticIP(ip, subnet, gateway, mac);
            NetworkInterface.EnableStaticDns(new byte[] { 10, 0, 64, 254 });

            Socket serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            //EndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 2000);
            //serversocket.Bind(localEndPoint);

            EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);

            while (true)
            {
                if (serversocket.Poll(-1, SelectMode.SelectRead))
                //if (serversocket.Available > 0)
                {
                    byte[] inBuf = new byte[serversocket.Available];
                    int count = serversocket.ReceiveFrom(inBuf, ref remoteEndPoint);
                    Debug.Print(new String(Encoding.UTF8.GetChars(inBuf)));
                }
            }

        }
    }

#9

[quote]I would like to see all incoming UDP messages from all IP addresses at all ports.
[/quote]

And I would like to date Heather Locklear. But in both of our cases it is not going to happen.

It is not possible to configure a udp socket to receive messages from all ports. You must specify a port.

Also “IPAddress.Any” does not mean you can receive a message from any remote IP address. It means you can receive through any local ip interface. Local ip interfaces are identified by their IP address.


#10

Yes, because your listening socket is not completely established.

These 3 lines:


Socket serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 2000);
serversocket.Bind(localEndPoint);

are required to start listening for incoming connections and you have to specify port.

Then you have to create a socket for each port you want to listen on.