G120 (Cobra II NET) Hangs performing a UDP Send

Having an issue trying to send UDP Datagrams on the G120. The following code works perfectly on a CANXtra (EMX) but freezes on the SendTo method of the Socket object. On another PC I am running a continuous ping to the G120. The module responds to the pings until the SendTo method is called. Are there any insights into this problem? Thanks!


Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress ipAddress = IPAddress.Parse("255.255.255.255");
IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, 6500);

new Thread(() =>
{
   byte[] messageSize;

   while (true)
   {
      lock (synchObject)
      {
           messageSize = BitConverter.GetBytes(frameCount);
           messageSize.CopyTo(broadcastBytes, 0);
           udpClient.SendTo(broadcastBytes, (frameCount * 64) + 4, SocketFlags.Broadcast, remoteEndPoint);  //Freezes here
           frameCount = 0;
       }
      Thread.Sleep(100);
    }

}).Start(); 


@ Diesel Engineer -

Just an example about “Bind” and “SendTo”


void ThreadTransferVoice()
        {
            Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 2535);
            mySocket.Bind(ipep);  ///////////=>>> Missing it??????????
            byte[] discoveryAddr = IPAddress.Parse("x.x.x.x").GetAddressBytes();
            IPAddress DestinationIP = new IPAddress(discoveryAddr);
            IPEndPoint DestinationEndPoint = new IPEndPoint(DestinationIP, 9050);
            while (true)
            {
                //while (mySocket.Poll(200000, SelectMode.SelectRead))
                {
                    if (userInputVoice.Length > 0)
                    {
                        
                        userInputVoice = userInputVoice.Replace(" ","");
                       userInputVoice= userInputVoice.ToUpper();
                        byte[] bytesToSend = Encoding.UTF8.GetBytes(userInputVoice);
                        Console.WriteLine("" + userInputVoice);
                        mySocket.SendTo(bytesToSend, DestinationEndPoint);
                        userInputVoice = "";
                        
                    }
                }
                Thread.Sleep(100);
            }
        }


@ Dat

Thank you for the advice, I will be sure to try this tomorrow. One question though, why does it work on the EMX platform without the Bind call? The Bind in your code is for receiving data? My example does not expect to receive data. Can you elaborate further please?

@ Dat

This change (as recommended in your code) did not improve the situation. Reducing the total packet size (bytes) did allow the SendTo command to work but nothing is received on the PC side on the desired port.

[ol]
I am able to ping the G120 from the PC when the application starts. This indicates the IP address is set correctly.
The exact same code functions correctly when compiled for 4.1 on a CANXtra (using the appropriate method for initializing the network port)[/ol]

Do you have any more suggestions please?

I agree UDP is ready to trace and should help quickly.

@ Diesel Engineer -

So 2 things:

  • SendTo works now because has limitation about size
  • SendTo works but on your PC doesn’t see it. This is another story.

You need to make sure the application on PC (I call it as Server) has configuration correctly (IP address, EndpointIP…)

Ping works but it doesn’t say anything. It just tell you your device is connected to current network. Even same code, but different macAddress, and if you use DHCP, IP address may be different.

Did you set your MAC address properly?

This is the code I am using to set the IP address of the G120.


class Network
    {
        private EthernetENC28J60 eth;

        public Network()
        {
            eth = new EthernetENC28J60(SPI.SPI_module.SPI2, Pin.P1_10, Pin.P2_11, Pin.P1_9, 4000);

            if (!eth.IsOpen)
                eth.Open();

            //if (!eth.NetworkInterface.IsDhcpEnabled)
            //    eth.NetworkInterface.EnableDhcp();

            eth.NetworkInterface.EnableStaticIP("10.182.2.174", "255.255.192.0", "10.182.0.1");
            eth.NetworkInterface.EnableStaticDns(new string[] { "10.180.100.59", "10.180.40.4" });

            NetworkInterfaceExtension.AssignNetworkingStackTo(eth);
        }
    }

All the responses here seem to disregard that this WORKS using a CANXtra (EMX) running the same code (except for initializing the network). The PC receiver app is known to work.

This is required on the Cobra II NET?

Thanks for your help.

I have a small program for this example.
I just ran again and it works fine.

Everything you need is change the line below as your PC address

IPAddress ip = new IPAddress(new byte[] {x,x,x,x}); /// This Address must be your PC address

PC:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace Test_UDP_PC
{
    class Program
    {
        static void Main(string[] args)
        {
            Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            IPEndPoint MyServiceEndPoint = new IPEndPoint(IPAddress.Any, 1234);
            mySocket.Bind(MyServiceEndPoint);
            while (true)
            {
                while (mySocket.Poll(200000, SelectMode.SelectRead))
                {
                    if (mySocket.Available > 0)
                    {
                        byte[] inBuf = new byte[mySocket.Available];
                        EndPoint recEndPoint = new IPEndPoint(IPAddress.Any, 0);
                        mySocket.ReceiveFrom(inBuf, ref recEndPoint);
                        Console.WriteLine("Message From " + ((IPEndPoint)recEndPoint).Address.ToString());
                        Console.WriteLine(new string(Encoding.UTF8.GetChars(inBuf)));
                        String msg = "Hello G120! I am PC";
                        byte[] bytesToSend = Encoding.UTF8.GetBytes(msg);
                        mySocket.SendTo(bytesToSend, bytesToSend.Length, SocketFlags.None,
                        (IPEndPoint)recEndPoint);
                    }
                }
            }
        }
    }
}

G120 - 

using System;
using Microsoft.SPOT;
using System;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Security;
//using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.Net;
using Microsoft.SPOT.Net.NetworkInformation;
using GHI.Premium.Net;
using GHI.Premium.Hardware;
using GHINET = GHI.Premium.Net;

namespace Test_UDP_G120
{
public class Program
{
//public static GHINET.EthernetBuiltIn ethernet_J11D;
static EthernetENC28J60 ethernet_NC28J60;// = new WiFiRS9110(SPI.SPI_module.SPI2, GHI.Hardware.G120.Pin.P1_10, GHI.Hardware.G120.Pin.P2_11, GHI.Hardware.G120.Pin.P1_9); // G120
static InputPort button = new InputPort((Cpu.Pin)22, false, Port.ResistorMode.PullUp); // Please connect a button to pin 30, socket 8
static OutputPort led = new OutputPort((Cpu.Pin)47, true);
static Boolean isNetworkConfigReady = false;

    public static void Main()
    {
        
        while (button.Read()) 
        {
            led.Write(true);
            Thread.Sleep(50);
            led.Write(false);
            Thread.Sleep(50);
        }
        StartComunication();

    }
    static void Interface_NetworkAddressChanged(object sender, EventArgs e)
    {
        isNetworkConfigReady = false;
        Debug.Print("New address for the Network Interface ");
        Debug.Print("Is DhCp enabled: " + ethernet_NC28J60.NetworkInterface.IsDhcpEnabled);
        Debug.Print("Is DynamicDnsEnabled enabled: " + ethernet_NC28J60.NetworkInterface.IsDynamicDnsEnabled);
        Debug.Print("NetworkInterfaceType " + ethernet_NC28J60.NetworkInterface.NetworkInterfaceType);
        Debug.Print("Network settings:");
        Debug.Print("IP Address: " + ethernet_NC28J60.NetworkInterface.IPAddress);
        Debug.Print("Subnet Mask: " + ethernet_NC28J60.NetworkInterface.SubnetMask);
        Debug.Print("Default Gateway: " + ethernet_NC28J60.NetworkInterface.GatewayAddress);
        Debug.Print("Number of DNS servers:" + ethernet_NC28J60.NetworkInterface.DnsAddresses.Length);
        for (int i = 0; i < ethernet_NC28J60.NetworkInterface.DnsAddresses.Length; i++)
            Debug.Print("DNS Server " + i.ToString() + ":" + ethernet_NC28J60.NetworkInterface.DnsAddresses[i]);
        Debug.Print("------------------------------------------------------");
        if (ethernet_NC28J60.NetworkInterface.IPAddress !="0.0.0.0")
                        isNetworkConfigReady = true;

    }
    static void StartComunication()
    {          
        //ethernet_J11D = new GHINET.EthernetBuiltIn();
        ethernet_NC28J60 = new GHI.Premium.Net.EthernetENC28J60(SPI.SPI_module.SPI2, GHI.Hardware.G120.Pin.P1_17, GHI.Hardware.G120.Pin.P2_21, GHI.Hardware.G120.Pin.P1_14, 4000); // G120
        //ethernet_J11D = new GHI.Premium.Net.EthernetENC28J60(SPI.SPI_module.SPI1, GHI.Hardware.EMX.Pin.IO15, GHI.Hardware.EMX.Pin.IO46, GHI.Hardware.EMX.Pin.IO6, 4000); // socket 9
        if (!ethernet_NC28J60.IsOpen)
            ethernet_NC28J60.Open();
        if (!ethernet_NC28J60.NetworkInterface.IsDhcpEnabled)
            ethernet_NC28J60.NetworkInterface.EnableDhcp();
        
        ethernet_NC28J60.NetworkAddressChanged += Interface_NetworkAddressChanged;
        GHI.Premium.Net.NetworkInterfaceExtension.AssignNetworkingStackTo(ethernet_NC28J60);

        while (isNetworkConfigReady == false) // wait for network is ready
        {
            Thread.Sleep(50);
        }
        System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        IPAddress ip = new IPAddress(new byte[] {x,x,x,x}); /// This Address must be your PC address
        IPEndPoint endPoint = new IPEndPoint(ip, 1234);
        socket.Connect(endPoint);

        String msg = "Hello PC, I am G120";
        byte[] bytesToSend = Encoding.UTF8.GetBytes(msg);
        while (true)
        {
            socket.SendTo(bytesToSend, bytesToSend.Length, SocketFlags.None, endPoint);
            while (socket.Poll(2000000, SelectMode.SelectRead))
            {
                if (socket.Available > 0)
                {
                    byte[] inBuf = new byte[socket.Available];
                    EndPoint recEndPoint = new IPEndPoint(IPAddress.Any, 0);
                    socket.ReceiveFrom(inBuf, ref recEndPoint);
                    if (!recEndPoint.Equals(endPoint))// Check if the received packet is from the 192.168.0.2
                        continue;
                    Debug.Print(new String(Encoding.UTF8.GetChars(inBuf)));
                }
            }
            Thread.Sleep(100);
        }
    }
}

}

@ Dat -

g120 send a message “Hello PC, I am G120”;
PC send a message “Hellp G120, I am PC”;

@ Dat

[quote]IPAddress ip = new IPAddress(new byte[] {x,x,x,x}); /// This Address must be your PC address
[/quote]

So broadcast is not possible on the G120? Works without it (Bind) on the EMX!

@ Diesel Engineer -

I don’t use Bind in G120


            System.Net.Sockets.Socket socket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            IPAddress ip = new IPAddress(new byte[] {x,x,x,x}); /// This Address must be your PC address
            IPEndPoint endPoint = new IPEndPoint(ip, 1234);
            socket.Connect(endPoint);
 
            String msg = "Hello PC, I am G120";
            byte[] bytesToSend = Encoding.UTF8.GetBytes(msg);
            while (true)
            {
                socket.SendTo(bytesToSend, bytesToSend.Length, SocketFlags.None, endPoint);


Your sample code sends to specific address, I wish to broadcast to multiple addresses.

@ Diesel Engineer -

OK, replace by:
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(“255.255.255.255”), 1234);

I tried it and works.

First of all I want to thank everyone for helping! :slight_smile: As a last ditch effort I connected the Cobra II NET directly to my laptop and ran the application and voila it works! Previously, I was attempting to transmit through our corporate network (worked with the EMX). I have seen other hardware do the same thing, not sure why this happens but it will not impact our project.

The remaining problem surrounds the maximum byte[] array size I can broadcast. RFC5405 suggest the maximum UDP datagram payload for IPV4 of 65507 bytes. The G120 seems to bomb around 2K. Does that seem right?

Thanks again!

@ andre.m -

There is an 8Kb buffer in the (SPI) ENC28J60 Ethernet controller. Documentation indicates you can specify the size of the send and receive buffers. I need about 4Kb of send buffer but don’t know how to specify it.

Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            udpClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, 4000); //Fails here
            IPAddress ipAddress = IPAddress.Parse("255.255.255.255");
            IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, 6500);

Fails with a:

#### SocketException ErrorCode = 10042

A first chance exception of type ‘System.Net.Sockets.SocketException’ occurred in Microsoft.SPOT.Net.dll

Which is:

[quote]Bad protocol option.
An unknown, invalid or unsupported option or level was specified in a getsockopt or setsockopt call.
[/quote]

Not even sure this is the correct way to specify the hardware send buffer size. Any thoughts? Thanks.