I'm using a shared class library (private, not a public one) that has a method that searches local networks for a Manufacturers Test box in order to commission the device my software is running on.
I am running a .Net 6 application on a Raspberry Pi 4 running Buster.
The search uses .Net Sockets, using the SendTo command and waits for the responses. This works running from Visual Studio on my Windows PC, it also works on a different but similar application on a Raspberry PI 3 running Stretch, using the same method.
But on the PI 4, I simply don't get any responses. I've looked on WireShark and it seems to be communicating but I'm not overly sure as I don't really understand this level of networking, but there are no obvious errors being reported at any stage.
public List<EthernetDevice> SearchLocalNetwork()
{
//EthernetDevice newDevice = new EthernetDevice();
var devices = new List<EthernetDevice>();
foreach (var adapter in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces())
{
foreach (var address in adapter.GetIPProperties().UnicastAddresses)
{
// We're only interested in IPv4 addresses for now
if (address.Address.AddressFamily != AddressFamily.InterNetwork)
{
continue;
}
// Ignore loopback addresses (e.g., 127.0.0.1)
if (IPAddress.IsLoopback(address.Address))
{
continue;
}
try
{
var ethernetSearch = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
ethernetSearch.ExclusiveAddressUse = false;
var data = new byte[4];
var bytBuffer = new byte[256];
var broadcastAddress = address.Address.GetAddressBytes();
/*if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
broadcastAddress[0] = 169;
broadcastAddress[1] = 254;
}*/
// broadcastAddress[2] = 255;
broadcastAddress[3] = 255;
var newAddress = new IPAddress(broadcastAddress);
Console.WriteLine("Broadcast Address: {0}", newAddress);
IPEndPoint responder = new IPEndPoint(IPAddress.Any, 0);
// IPEndPoint responder = new IPEndPoint(newAddress, 0);
EndPoint rep = (EndPoint)responder; // this will be IP Address and Port number: 192.168.10.123:30716
int i, endtime;
//////////////////////////////////////////////////////////////
// Set up a UDP Socket which can broadcast to entire network
//////////////////////////////////////////////////////////////
ethernetSearch.EnableBroadcast = true;
ethernetSearch.ReceiveTimeout = 8000;
ethernetSearch.ExclusiveAddressUse = false;
// Define an EndPoint which can be used to broadcast. Port 0x77FE
// is the configuration port of the XPort Direct.
//
// IPEndPoint ep = new IPEndPoint(System.Net.IPAddress.Broadcast, 0x77FE);
var ep = new IPEndPoint(newAddress, 0x77FE);
// Set up a message to send, requesting configuration register.
// Message F8 does this, and should initiate a reply of F9 followed
// by the register details in HEX format
for (i = 0; i < 4; data[i++] = 0);
data[3] = 0xF8;
// Broadcast the message
ethernetSearch.SendTo(data, ep);
// The following block of code will run continually until
// no more replies are received. At this point, a Socket
// Exception will be thrown, and then caught in the Catch
// statement. Initially the receive timeout is set to 7000ms
// as it takes a while for the broadcast message to go out
// and the devices to initiate a reply. After that, they
// respond very quickly in succession, so the receive timeout
// is reduced to 700ms to reduce the waiting time after the last
// reply is received
//
// The IP Address which sent the response is extracted from the Responding
// End Point (REP).
endtime = Environment.TickCount + 7000;
while (true) // this loop will be exited by the 'break' statement when no more replies are received
{
while (Environment.TickCount < endtime && ethernetSearch.Available == 0)
{
Thread.Sleep(2);
}
if (ethernetSearch.Available > 0)
{
ethernetSearch.ReceiveFrom(bytBuffer, ref rep);
}
else
{
break;
}
if (bytBuffer[3] == 0xF9) // verify reply code - response to F8 is F9
{
var iPAdd = rep.ToString().Substring(0, rep.ToString().IndexOf(':'));
var port = bytBuffer[25] * 256 + bytBuffer[24];
iPAdd += ":" + port;
var isDhcp = false;
if (bytBuffer[4] == 0 && bytBuffer[5] == 0 && bytBuffer[6] == 0 && bytBuffer[7] == 0)
{
isDhcp = true;
}
var device = new EthernetDevice();
device.IPAddress = iPAdd.Split(':')[0];
device.Port = port;
device.DHCP = isDhcp;
device.Gateway = bytBuffer[16] + "." + bytBuffer[17] + "." + bytBuffer[18] + "." +
bytBuffer[19];
device.BaudRate = 2;
devices.Add(device);
//if (devices.FirstOrDefault(x => x.IPAddress == device.IPAddress) == null)
//{
// devices.Add(device);
//}
// Set up new end time for waiting for next device
endtime = Environment.TickCount + 700;
}
}
// sort the resulting list by IP Address order
ethernetSearch.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
return devices;
}
Its a bit rough but returns a list of test boxes across any networks it detects.
Does anyone have any ideas, is this a OS/Buster issue or a code issue? I'm thinking its more OS at this stage.
I did try setting the buffer sizes in sysctl.conf but is didn't help.
net.core.rmem_max = 16777216
net.core.wmem_max = 4194304
The issue was solved by resetting all UFW rules on the device.
sudo ufw reset