Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions NetSdrClientApp/Networking/IUdpClient.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@

public interface IUdpClient
namespace NetSdrClientApp.Networking
{
event EventHandler<byte[]>? MessageReceived;
public interface IUdpClient
{
event EventHandler<byte[]>? MessageReceived;

Task StartListeningAsync();
Task StartListeningAsync();

void StopListening();
void Exit();
}
void StopListening();

void Exit();
}
}
117 changes: 65 additions & 52 deletions NetSdrClientApp/Networking/UdpClientWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,85 +1,98 @@
using System;
using System;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NetSdrClientApp.Networking;

public class UdpClientWrapper : IUdpClient
namespace NetSdrClientApp.Networking
{
private readonly IPEndPoint _localEndPoint;
private CancellationTokenSource? _cts;
private UdpClient? _udpClient;

public event EventHandler<byte[]>? MessageReceived;

public UdpClientWrapper(int port)
public class UdpClientWrapper : IUdpClient, IDisposable
{
_localEndPoint = new IPEndPoint(IPAddress.Any, port);
}
private readonly IPEndPoint _localEndPoint;
private CancellationTokenSource? _cts;
private UdpClient? _udpClient;
private bool _disposed;

public async Task StartListeningAsync()
{
_cts = new CancellationTokenSource();
Console.WriteLine("Start listening for UDP messages...");
public event EventHandler<byte[]>? MessageReceived;

try
public UdpClientWrapper(int port)
{
_udpClient = new UdpClient(_localEndPoint);
while (!_cts.Token.IsCancellationRequested)
_localEndPoint = new IPEndPoint(IPAddress.Any, port);
}

public async Task StartListeningAsync()
{
_cts = new CancellationTokenSource();
Console.WriteLine("Start listening for UDP messages...");

try
{
UdpReceiveResult result = await _udpClient.ReceiveAsync(_cts.Token);
MessageReceived?.Invoke(this, result.Buffer);
_udpClient = new UdpClient(_localEndPoint);

while (!_cts.Token.IsCancellationRequested)
{
UdpReceiveResult result = await _udpClient.ReceiveAsync(_cts.Token);
MessageReceived?.Invoke(this, result.Buffer);

Console.WriteLine($"Received from {result.RemoteEndPoint}");
Console.WriteLine($"Received from {result.RemoteEndPoint}");
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Listening cancelled.");
}
catch (Exception ex)
{
Console.WriteLine($"Error receiving message: {ex.Message}");
}
}
catch (OperationCanceledException ex)
{
//empty
}
catch (Exception ex)
{
Console.WriteLine($"Error receiving message: {ex.Message}");
}
}

public void StopListening()
{
try
public void StopListening()
{
_cts?.Cancel();
_udpClient?.Close();
Console.WriteLine("Stopped listening for UDP messages.");
}
catch (Exception ex)

public void Exit()
{
Console.WriteLine($"Error while stopping: {ex.Message}");
StopListening();
}
}

public void Exit()
{
try
public override bool Equals(object? obj)
{
_cts?.Cancel();
_udpClient?.Close();
Console.WriteLine("Stopped listening for UDP messages.");
if (obj is not UdpClientWrapper other) return false;

return _localEndPoint.Port == other._localEndPoint.Port &&
_localEndPoint.Address.Equals(other._localEndPoint.Address);
}

public override int GetHashCode()
{
return HashCode.Combine(_localEndPoint.Address, _localEndPoint.Port);
}
catch (Exception ex)

public void Dispose()
{
Console.WriteLine($"Error while stopping: {ex.Message}");
Dispose(true);
GC.SuppressFinalize(this);
}
}

public override int GetHashCode()
{
var payload = $"{nameof(UdpClientWrapper)}|{_localEndPoint.Address}|{_localEndPoint.Port}";
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;

using var md5 = MD5.Create();
var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(payload));
if (disposing)
{
_cts?.Cancel();
_cts?.Dispose();
_udpClient?.Dispose();
}

return BitConverter.ToInt32(hash, 0);
_disposed = true;
}
}
}
}
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
Usage:
C - connect
D - disconnet
F - set frequency
S - Start/Stop IQ listener
Q - quit
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=olekca160406_NetSdrClient&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=olekca160406_NetSdrClient)
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=olekca160406_NetSdrClient&metric=bugs)](https://sonarcloud.io/summary/new_code?id=olekca160406_NetSdrClient)
[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=olekca160406_NetSdrClient&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=olekca160406_NetSdrClient)
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=olekca160406_NetSdrClient&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=olekca160406_NetSdrClient)
[![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=olekca160406_NetSdrClient&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=olekca160406_NetSdrClient)