sockets & receiving broadcasts not working when in a MAUI App – C#

  Kiến thức lập trình

I use Rider on Mac, and im having some troubles with not being able to receive broadcasts on port 15000, only when in a MAUI App. Here is some code in a console solution:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Newtonsoft.Json; // Add this if using Newtonsoft.Json for JSON parsing

public class IFConnect
{
    private UdpClient udpClient;
    private IPEndPoint endPoint;
    private string device_ip;

    public void EstablishConnection(bool logStatus = false)
    {
        udpClient = new UdpClient(15000);
        endPoint = new IPEndPoint(IPAddress.Any, 15000);

        if (logStatus)
            Console.WriteLine("Connecting to Infinite Flight...");

        StartListening();
    }

    private void StartListening()
    {
        udpClient.BeginReceive(new AsyncCallback(OnUdpDataReceived), null);
    }

    private void OnUdpDataReceived(IAsyncResult ar)
    {
        byte[] data = udpClient.EndReceive(ar, ref endPoint);
        string receivedData = Encoding.UTF8.GetString(data);
        Console.WriteLine($"Received '{receivedData}' from {endPoint}");

        // Example processing: Parsing JSON (assuming the data is JSON-formatted)
        dynamic response = JsonConvert.DeserializeObject(receivedData);
        string addr = GetIPAddr(response.Addresses ?? response.addresses);

        Console.WriteLine(response);
        Console.WriteLine(addr);

        if (!string.IsNullOrEmpty(addr) && (response.Port != null || response.port != null))
        {
            device_ip = addr;
            // Proceed with TCP connection or any other logic here
            // ConnectAPI();
        }

        // Continue listening for the next UDP packet
        StartListening();
    }

    private string GetIPAddr(dynamic addresses)
    {
        // Add your logic to extract and return the IP address
        return addresses[0].ToString();  // Example logic
    }
}

class Program
{
    static void Main(string[] args)
    {
        IFConnect ifConnect = new IFConnect();
        ifConnect.EstablishConnection(true); // Pass 'true' to log status
        Console.ReadLine(); // Keep the console open
    }
}

which works perfectly and fast as expected.

However, when I run it in a MAUI app, either in a separate CS file and using it, or having it in the MainPage.xaml.cs file, it either does not work or gives me permission denied. Here are some examples:

  1. Permission Denied:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json; // Ensure you have this package installed
using Microsoft.Maui.Controls; // Ensure you are using the correct namespace for MAUI

namespace InfiniteConnect
{
    public partial class MainPage : ContentPage
    {
        private UdpClient udpClient;
        private IPEndPoint endPoint;
        private string device_ip;

        public MainPage()
        {
            InitializeComponent();
            StartUdpClient();
        }

        private async void StartUdpClient()
        {
            try
            {
                udpClient = new UdpClient(15000);
                endPoint = new IPEndPoint(IPAddress.Any, 15000);

                // Start receiving data asynchronously
                await Task.Run(() => ListenForMessages());
            }
            catch (Exception ex)
            {
                // Handle exceptions if needed
                Console.WriteLine($"Exception: {ex.Message}");
            }
        }

        private async void ListenForMessages()
        {
            while (true)
            {
                try
                {
                    var data = await udpClient.ReceiveAsync();
                    var receivedData = Encoding.UTF8.GetString(data.Buffer);

                    // Process received data
                    await ProcessReceivedData(receivedData);
                }
                catch (Exception ex)
                {
                    // Handle exceptions if needed
                    Console.WriteLine($"Exception: {ex.Message}");
                }
            }
        }

        private async Task ProcessReceivedData(string data)
        {
            // This method should run on the main thread if it updates UI components
            await MainThread.InvokeOnMainThreadAsync(() =>
            {
                Console.WriteLine($"Received '{data}' from {endPoint}");
                dynamic response = JsonConvert.DeserializeObject(data);
                string addr = GetIPAddr(response.Addresses ?? response.addresses);

                Console.WriteLine(response);
                Console.WriteLine(addr);

                if (!string.IsNullOrEmpty(addr) && (response.Port != null || response.port != null))
                {
                    device_ip = addr;
                    // Update UI or handle connection logic here
                }
            });
        }

        private string GetIPAddr(dynamic addresses)
        {
            // Add your logic to extract and return the IP address
            return addresses[0].ToString();  // Example logic
        }
    }
}

and I simply get:
2024-08-19 22:22:11.728 InfiniteConnect[23296:525617] Exception: Permission denied
I have checked all firewalls and setting etc but do let me know any I might have missed.

  1. No response:
    ifc.cs:
// IFConnect.cs
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Newtonsoft.Json;

public class IFConnect
{
    public class Data
    {
        public Data(dynamic data)
        {
            // Initialize your Data object with the data here
        }
    }

    private string device_ip;
    private int device_port = 15000;  // Assuming the port is 15000, set it as required
    private TcpClient tcp;
    private UdpClient udp;
    private dynamic device_info;
    private Data info;

    public string Connect(string deviceIp = null)
    {
        Console.WriteLine("Starting connection process...");

        if (string.IsNullOrEmpty(deviceIp))
        {
            Console.WriteLine("No device IP provided, discovering devices...");
            udp = new UdpClient(15000);
            IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 15000);

            while (true)
            {
                byte[] receivedBytes = udp.Receive(ref remoteEndPoint);
                if (receivedBytes != null && receivedBytes.Length > 0)
                {
                    string receivedData = Encoding.UTF8.GetString(receivedBytes);
                    device_info = JsonConvert.DeserializeObject(receivedData);
                    info = new Data(device_info);
                    device_ip = remoteEndPoint.Address.ToString();
                    Console.WriteLine($"Device found: {device_info["DeviceName"]}, IP: {device_ip}");
                    udp.Close();
                    break;
                }
            }
        }
        else
        {
            device_ip = deviceIp;
            Console.WriteLine($"Using provided device IP: {device_ip}");
        }

        try
        {
            tcp = new TcpClient();
            tcp.Connect(device_ip, device_port);
            Console.WriteLine($"Connected to Infinite Flight Connect: {device_info["DeviceName"]}, IP: {device_ip}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Failed to connect: {ex.Message}");
            return "Connection failed.";
        }

        // shutdown_tcp(); // Implement this method if needed
        return "Connected! Have a nice flight!";
    }
}

MainPage.xaml.cs:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json; // Ensure you have this package installed
using Microsoft.Maui.Controls; // Ensure you are using the correct namespace for MAUI
    
namespace InfiniteConnect
{
    public partial class MainPage : ContentPage
    {
        private UdpClient udpClient;
        private IPEndPoint endPoint;
        private string device_ip;

        public MainPage()
        {
            InitializeComponent();
            IFConnect ifc = new IFConnect();
            
            // Start the connection process
            Task.Run(() =>
            {
                string deviceIp = null;
                ifc.Connect(deviceIp);
            });
        }
    
        
    }
}

But I simply get:

2024-08-19 22:23:52.746 InfiniteConnect[23399:527862] Starting connection process...
2024-08-19 22:23:52.746 InfiniteConnect[23399:527862] No device IP provided, discovering devices...

Both of these should return some data which I then decode, but do not even get past:
udp = new UdpClient(15000);
in 2

I have done a lot of research about this but nothing will work. The docs for receiving the packets are:
If the IP address of the device to connect to is unknown, it is possible to discover existing devices on the same local network using UDP. We broadcast UDP packets on port 15000 which provide the IP address of the device among other details.

Thanks.

New contributor

robinb is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT