Oakrey.Network.IpScanner
2.0.3
dotnet add package Oakrey.Network.IpScanner --version 2.0.3
NuGet\Install-Package Oakrey.Network.IpScanner -Version 2.0.3
<PackageReference Include="Oakrey.Network.IpScanner" Version="2.0.3" />
<PackageVersion Include="Oakrey.Network.IpScanner" Version="2.0.3" />
<PackageReference Include="Oakrey.Network.IpScanner" />
paket add Oakrey.Network.IpScanner --version 2.0.3
#r "nuget: Oakrey.Network.IpScanner, 2.0.3"
#:package Oakrey.Network.IpScanner@2.0.3
#addin nuget:?package=Oakrey.Network.IpScanner&version=2.0.3
#tool nuget:?package=Oakrey.Network.IpScanner&version=2.0.3
Oakrey.Network.IpScanner
Asynchronous IPv4 network scanner library for .NET.
Pings every address in an IpAddressRange concurrently and streams discovered devices in real time through an IObservable<NetworkDeviceInfo> interface.
Features
IP range scanning
IpScanner.Scan(IpAddressRange, CancellationToken) expands the range into individual IP strings via IpAddressRangeExtensions.GetIpRange and fires all ICMP pings concurrently with Task.WhenAll.
Reactive device stream
IpScanner implements IObservable<NetworkDeviceInfo>. Internally it uses a ReplaySubject<NetworkDeviceInfo>, so late subscribers receive all devices found before they subscribed. The stream completes when all pings have finished.
Scan progress
IpScanner.RemainingScans is an IObservable<int> backed by a BehaviorSubject. It emits the number of pending pings after each reply and emits 0 when the scan is complete. Useful for driving a progress indicator.
Device resolution
Each discovered device is represented by NetworkDeviceInfo (from Oakrey.Network.Tools):
| Member | Type | Description |
|---|---|---|
IpAddress |
IPAddress |
Address that replied to the ping |
PingReply |
PingReply? |
Full System.Net.NetworkInformation.PingReply |
MacAddress |
string |
Resolved via ResolveMacAddressAndType(), default "Unresolved" |
Type |
string |
Device/adapter type, resolved via ResolveMacAddressAndType() |
Name |
string |
DNS hostname, resolved via ResolveName(CancellationToken) |
Cancellation and error handling
Cancellation is passed through to every Ping.SendPingAsync call. Cancelled pings are traced and silently skipped. Unexpected errors are logged and re-thrown from Scan.
Architecture
classDiagram
class IpScanner {
+IObservable~NetworkDeviceInfo~ (implements)
+IObservable~int~ RemainingScans
+Task Scan(IpAddressRange, CancellationToken)
+IDisposable Subscribe(IObserver~NetworkDeviceInfo~)
-ReplaySubject~NetworkDeviceInfo~ discoveredDevices
-BehaviorSubject~int~ remainingScans
-CountdownEvent countdown
-TimeSpan pingTimeoutSec
}
class IpAddressRangeExtensions {
+List~string~ GetIpRange(IpAddressRange, CountdownEvent)
}
class NetworkDeviceInfo {
+IPAddress IpAddress
+PingReply? PingReply
+string MacAddress
+string Name
+string Type
+ResolveMacAddressAndType()
+Task ResolveName(CancellationToken)
}
IpScanner --> IpAddressRangeExtensions : uses
IpScanner --> NetworkDeviceInfo : emits
Requirements
- .NET 10 or higher
Oakrey.Network.Abstractions(transitive)Oakrey.Network.Tools(transitive)Oakrey.Log(transitive)
Installation
NuGet Package Manager
- Open Visual Studio.
- Go to Tools > NuGet Package Manager > Manage NuGet Packages for Solution.
- Search for
Oakrey.Network.IpScannerand click Install.
.NET CLI
dotnet add package Oakrey.Network.IpScanner
Package Manager Console
Install-Package Oakrey.Network.IpScanner
Example usage
Basic scan with device subscription
IpAddressRange range = new("192.168.1.1-254");
IpScanner scanner = new();
// Subscribe before calling Scan to avoid missing early results.
// Late subscribers will still receive all results due to ReplaySubject.
using IDisposable subscription = scanner.Subscribe(device =>
{
Console.WriteLine($"Found: {device.IpAddress}");
device.ResolveMacAddressAndType();
await device.ResolveName(CancellationToken.None);
Console.WriteLine($" Name: {device.Name} MAC: {device.MacAddress} Type: {device.Type}");
});
await scanner.Scan(range, CancellationToken.None);
Tracking progress
using IDisposable progress = scanner.RemainingScans.Subscribe(remaining =>
{
Console.WriteLine($"Remaining pings: {remaining}");
});
await scanner.Scan(range, CancellationToken.None);
Cancelling a long-running scan
using CancellationTokenSource cts = new(TimeSpan.FromSeconds(15));
try
{
await scanner.Scan(range, cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Scan was cancelled.");
}
Collecting all results after the scan completes
List<NetworkDeviceInfo> results = await scanner.ToList();
// scanner is IObservable<NetworkDeviceInfo>, so Rx ToList() collects until OnCompleted.
Development notes
- The ping timeout is fixed at 10 seconds per address (
TimeSpan.FromSeconds(10)). All pings run concurrently, so wall-clock time for a /24 range is bounded by this timeout, not by the number of addresses. ReplaySubject<NetworkDeviceInfo>has no buffer limit; it replays the full history to any late subscriber. If scanning very large ranges, consider whether late replay is desirable.IpScanneris not thread-safe for concurrent calls toScan. TheCountdownEventis reset at the start of each scan; callingScanconcurrently will corrupt the countdown state.NetworkDeviceInfomembersMacAddress,Name, andTypedefault to"Unresolved". CallResolveMacAddressAndType()andResolveName(CancellationToken)explicitly after receiving the device from the observable.
License
MIT - Copyright (c) Oakrey 2016-present
- Repository: Azure DevOps
- NuGet: Oakrey.Network.IpScanner
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Oakrey.Log (>= 2.0.0)
- Oakrey.Network.Abstractions (>= 2.0.3)
- Oakrey.Network.Tools (>= 2.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.