Skip to content

Commit b2e8d52

Browse files
author
LoneWandererProductions
committed
scmall cleanup
1 parent 7c532aa commit b2e8d52

3 files changed

Lines changed: 56 additions & 32 deletions

File tree

Communication/FileTransfer.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
namespace Communication
1818
{
19+
/// <summary>
20+
/// Helper class for file transfers, including downloading files from URLs and saving them to disk.
21+
/// </summary>
1922
internal static class FileTransfer
2023
{
2124
/// <summary>

Communication/Listener.cs

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Net.Sockets;
1212
using System.Text;
1313
using System.Threading;
14+
using System.Threading.Tasks;
1415

1516
namespace Communication
1617
{
@@ -48,32 +49,36 @@ public Listener(int port)
4849
/// Starts the listening.
4950
/// </summary>
5051
/// <param name="cancellationToken">The cancellation token.</param>
51-
public void StartListening(CancellationToken cancellationToken)
52+
public async Task StartListeningAsync(CancellationToken cancellationToken)
5253
{
5354
_isRunning = true;
5455
_tcpListener.Start();
5556
Console.WriteLine(ComResource.MessageListening, _port);
56-
while (_isRunning)
57+
58+
try
5759
{
58-
if (cancellationToken.IsCancellationRequested)
60+
// We use the CancellationToken to stop the loop gracefully
61+
while (!cancellationToken.IsCancellationRequested && _isRunning)
5962
{
60-
StopListening();
61-
return;
62-
}
63+
// This blocks asynchronously: 0% CPU usage while waiting
64+
using var client = await _tcpListener.AcceptTcpClientAsync(cancellationToken);
6365

64-
try
65-
{
66-
if (_tcpListener.Pending()) // Non-blocking accept
67-
{
68-
var client = _tcpListener.AcceptTcpClient();
69-
ThreadPool.QueueUserWorkItem(HandleClient, client);
70-
}
71-
}
72-
catch (Exception ex)
73-
{
74-
Console.WriteLine(ComResource.ErrorAcceptingCommunication, ex.Message);
66+
// Fire and forget the handler so we can accept the next client immediately
67+
_ = HandleClientAsync(client);
7568
}
7669
}
70+
catch (OperationCanceledException)
71+
{
72+
// Normal exit when token is cancelled
73+
}
74+
catch (Exception ex)
75+
{
76+
Console.WriteLine(ComResource.ErrorAcceptingCommunication, ex.Message);
77+
}
78+
finally
79+
{
80+
StopListening();
81+
}
7782
}
7883

7984
/// <summary>
@@ -90,17 +95,26 @@ public void StopListening()
9095
/// Handles the client.
9196
/// </summary>
9297
/// <param name="obj">The object.</param>
93-
private static void HandleClient(object obj)
98+
private static async Task HandleClientAsync(TcpClient client)
9499
{
95-
var client = (TcpClient)obj;
96-
var stream = client.GetStream();
97-
// Respond with a simple message (acting as the "ping response")
98-
const string response = ComResource.AnswerMessage;
99-
var buffer = Encoding.ASCII.GetBytes(response);
100-
stream.Write(buffer, 0, buffer.Length);
101-
// Close the connection
102-
client.Close();
103-
Console.WriteLine(ComResource.MessageAnswer);
100+
try
101+
{
102+
using (client) // Ensures the client is closed
103+
using (var stream = client.GetStream()) // Ensures the stream is closed
104+
{
105+
byte[] buffer = Encoding.ASCII.GetBytes(ComResource.AnswerMessage);
106+
107+
// Use Async write
108+
await stream.WriteAsync(buffer, 0, buffer.Length);
109+
await stream.FlushAsync();
110+
111+
Console.WriteLine(ComResource.MessageAnswer);
112+
}
113+
}
114+
catch (Exception ex)
115+
{
116+
Console.WriteLine("Error handling client: " + ex.Message);
117+
}
104118
}
105119
}
106120
}

CommunicationTests/Communication.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,19 @@ public class Communication
3030
public async Task CommunicationsAsync()
3131
{
3232
var communication = new NetCom();
33-
_ = await communication.SaveFile(_path, "https://www.google.de/");
34-
var path = Path.Combine(Directory.GetCurrentDirectory(), nameof(Communication), "www.google.de");
33+
// Use a URL that actually ends in a filename
34+
string url = "https://www.google.de/favicon.ico";
35+
string targetFolder = Path.Combine(Directory.GetCurrentDirectory(), "TestDownloads");
3536

36-
Assert.IsTrue(File.Exists(path), "File not found");
37+
bool success = await communication.SaveFile(targetFolder, url);
3738

38-
File.Delete(path);
39+
// The helper logic will extract "favicon.ico"
40+
var expectedPath = Path.Combine(targetFolder, "favicon.ico");
41+
42+
Assert.IsTrue(success, "Download failed");
43+
Assert.IsTrue(File.Exists(expectedPath), $"File not found at {expectedPath}");
44+
45+
if (File.Exists(expectedPath)) File.Delete(expectedPath);
3946
}
4047

4148
/// <summary>
@@ -50,7 +57,7 @@ public async Task ListenerShouldRespondWithPongWhenPinged()
5057
var cancellationTokenSource = new CancellationTokenSource();
5158

5259
// Start the listener in a separate task to simulate real-world usage
53-
var listenerTask = Task.Run(() => listener.StartListening(cancellationTokenSource.Token),
60+
var listenerTask = Task.Run(() => listener.StartListeningAsync(cancellationTokenSource.Token),
5461
cancellationTokenSource.Token);
5562

5663
// Wait for a brief moment to ensure the server is up and listening

0 commit comments

Comments
 (0)