Skip to content
Closed
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
Binary file added .DS_Store
Binary file not shown.
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "weekly"
18 changes: 9 additions & 9 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ jobs:
dotnet tool install --global dotnet-sonarscanner
echo "$env:USERPROFILE\.dotnet\tools" >> $env:GITHUB_PATH
dotnet sonarscanner begin `
/k:"ppanchen_NetSdrClient" `
/o:"ppanchen" `
/k:"Dandddyy_ReengineeringCourse" `
/o:"dandddyy" `
/d:sonar.token="${{ secrets.SONAR_TOKEN }}" `
/d:sonar.cs.opencover.reportsPaths="**/coverage.xml" `
/d:sonar.cpd.cs.minimumTokens=40 `
Expand All @@ -70,13 +70,13 @@ jobs:
run: dotnet restore NetSdrClient.sln
- name: Build
run: dotnet build NetSdrClient.sln -c Release --no-restore
#- name: Tests with coverage (OpenCover)
# run: |
# dotnet test NetSdrClientAppTests/NetSdrClientAppTests.csproj -c Release --no-build `
# /p:CollectCoverage=true `
# /p:CoverletOutput=TestResults/coverage.xml `
# /p:CoverletOutputFormat=opencover
# shell: pwsh
- name: Tests with coverage (OpenCover)
run: |
dotnet test NetSdrClient.sln -c Release --no-build `
/p:CollectCoverage=true `
/p:CoverletOutput=TestResults/coverage.xml `
/p:CoverletOutputFormat=opencover
shell: pwsh
# 3) END: SonarScanner
- name: SonarScanner End
run: dotnet sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
Expand Down
80 changes: 80 additions & 0 deletions EchoTcpServer/EchoServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace EchoTcpServer
{
public class EchoServer : IDisposable
{
private readonly IPAddress _ipAddress;
private readonly int _port;
private TcpListener? _listener;
private CancellationTokenSource _cancellationTokenSource;

public EchoServer(IPAddress ipAddress, int port)
{
_ipAddress = ipAddress;
_port = port;
_cancellationTokenSource = new CancellationTokenSource();
}

public async Task StartAsync()
{
_listener = new TcpListener(_ipAddress, _port);
_listener.Start();
Console.WriteLine($"Server started on {_ipAddress}:{_port}.");

try
{
while (!_cancellationTokenSource.Token.IsCancellationRequested)
{
TcpClient client = await _listener.AcceptTcpClientAsync(_cancellationTokenSource.Token);
Console.WriteLine("Client connected.");
_ = Task.Run(() => HandleClientAsync(client, _cancellationTokenSource.Token));
}
}
catch (OperationCanceledException) { /* Очікувано при вимкненні */ }
catch (Exception ex) { Console.WriteLine($"Server error: {ex.Message}"); }
finally { Console.WriteLine("Server shutdown."); }
}

private async Task HandleClientAsync(TcpClient client, CancellationToken token)
{
using (client)
using (NetworkStream stream = client.GetStream())
{
try
{
byte[] buffer = new byte[8192];
int bytesRead;
while (!token.IsCancellationRequested && (bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0)
{
await stream.WriteAsync(buffer, 0, bytesRead, token);
Console.WriteLine($"Echoed {bytesRead} bytes to the client.");
}
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
Console.WriteLine($"Error handling client: {ex.Message}");
}
}
}

public void Stop()
{
if (!_cancellationTokenSource.IsCancellationRequested)
{
_cancellationTokenSource.Cancel();
}
_listener?.Stop();
}

public void Dispose()
{
Stop();
_cancellationTokenSource.Dispose();
}
}
}
2 changes: 1 addition & 1 deletion EchoTcpServer/EchoServer.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
Expand Down
20 changes: 20 additions & 0 deletions EchoTcpServer/IUdpClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics.CodeAnalysis;

namespace EchoTcpServer
{
public interface IUdpClient : IDisposable
{
void Send(byte[] dgram, int bytes, IPEndPoint endPoint);
}

[ExcludeFromCodeCoverage]
public class StandardUdpClient : IUdpClient
{
private readonly UdpClient _client = new UdpClient();
public void Send(byte[] dgram, int bytes, IPEndPoint endPoint) => _client.Send(dgram, bytes, endPoint);
public void Dispose() => _client.Dispose();
}
}
166 changes: 11 additions & 155 deletions EchoTcpServer/Program.cs
Original file line number Diff line number Diff line change
@@ -1,173 +1,29 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics.CodeAnalysis;

/// <summary>
/// This program was designed for test purposes only
/// Not for a review
/// </summary>
public class EchoServer
namespace EchoTcpServer
{
private readonly int _port;
private TcpListener _listener;
private CancellationTokenSource _cancellationTokenSource;


public EchoServer(int port)
[ExcludeFromCodeCoverage]
public class Program
{
_port = port;
_cancellationTokenSource = new CancellationTokenSource();
}

public async Task StartAsync()
{
_listener = new TcpListener(IPAddress.Any, _port);
_listener.Start();
Console.WriteLine($"Server started on port {_port}.");

while (!_cancellationTokenSource.Token.IsCancellationRequested)
public static async Task Main(string[] args)
{
try
{
TcpClient client = await _listener.AcceptTcpClientAsync();
Console.WriteLine("Client connected.");
using var server = new EchoServer(IPAddress.Any, 5000);
_ = Task.Run(() => server.StartAsync());

_ = Task.Run(() => HandleClientAsync(client, _cancellationTokenSource.Token));
}
catch (ObjectDisposedException)
{
// Listener has been closed
break;
}
}
using var standardUdpClient = new StandardUdpClient();
using var sender = new UdpTimedSender("127.0.0.1", 60000, standardUdpClient);

Console.WriteLine("Server shutdown.");
}

private async Task HandleClientAsync(TcpClient client, CancellationToken token)
{
using (NetworkStream stream = client.GetStream())
{
try
{
byte[] buffer = new byte[8192];
int bytesRead;

while (!token.IsCancellationRequested && (bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0)
{
// Echo back the received message
await stream.WriteAsync(buffer, 0, bytesRead, token);
Console.WriteLine($"Echoed {bytesRead} bytes to the client.");
}
}
catch (Exception ex) when (!(ex is OperationCanceledException))
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
client.Close();
Console.WriteLine("Client disconnected.");
}
}
}

public void Stop()
{
_cancellationTokenSource.Cancel();
_listener.Stop();
_cancellationTokenSource.Dispose();
Console.WriteLine("Server stopped.");
}

public static async Task Main(string[] args)
{
EchoServer server = new EchoServer(5000);

// Start the server in a separate task
_ = Task.Run(() => server.StartAsync());

string host = "127.0.0.1"; // Target IP
int port = 60000; // Target Port
int intervalMilliseconds = 5000; // Send every 3 seconds

using (var sender = new UdpTimedSender(host, port))
{
Console.WriteLine("Press any key to stop sending...");
sender.StartSending(intervalMilliseconds);
sender.StartSending(5000);

Console.WriteLine("Press 'q' to quit...");
while (Console.ReadKey(intercept: true).Key != ConsoleKey.Q)
{
// Just wait until 'q' is pressed
}
while (Console.ReadKey(intercept: true).Key != ConsoleKey.Q) { }

sender.StopSending();
server.Stop();
Console.WriteLine("Sender stopped.");
}
}
}


public class UdpTimedSender : IDisposable
{
private readonly string _host;
private readonly int _port;
private readonly UdpClient _udpClient;
private Timer _timer;

public UdpTimedSender(string host, int port)
{
_host = host;
_port = port;
_udpClient = new UdpClient();
}

public void StartSending(int intervalMilliseconds)
{
if (_timer != null)
throw new InvalidOperationException("Sender is already running.");

_timer = new Timer(SendMessageCallback, null, 0, intervalMilliseconds);
}

ushort i = 0;

private void SendMessageCallback(object state)
{
try
{
//dummy data
Random rnd = new Random();
byte[] samples = new byte[1024];
rnd.NextBytes(samples);
i++;

byte[] msg = (new byte[] { 0x04, 0x84 }).Concat(BitConverter.GetBytes(i)).Concat(samples).ToArray();
var endpoint = new IPEndPoint(IPAddress.Parse(_host), _port);

_udpClient.Send(msg, msg.Length, endpoint);
Console.WriteLine($"Message sent to {_host}:{_port} ");
}
catch (Exception ex)
{
Console.WriteLine($"Error sending message: {ex.Message}");
}
}

public void StopSending()
{
_timer?.Dispose();
_timer = null;
}

public void Dispose()
{
StopSending();
_udpClient.Dispose();
}
}
Loading