C# NetworkInterface
last modified October 18, 2026
In this article we show how to work with network interfaces in C#.
A network interface is the point of interconnection between a computer and a private or public network. It can be a physical network interface card (NIC) or implemented as a virtual software interface, such as the loopback interface or a bridge created by Docker.
NetworkInterface provides configuration and statistical information
for a network interface. It is available in the
System.Net.NetworkInformation namespace.
$ ls /sys/class/net/ lo wlp0s20f3
On Linux, we can find available interfaces in the /sys/class/net
directory. The ip link command lists them as well. On Windows, we
can use the ipconfig command.
C# GetIsNetworkAvailable
The GetIsNetworkAvailable method indicates whether any network
connection is available.
using System.Net.NetworkInformation;
if (NetworkInterface.GetIsNetworkAvailable())
{
Console.WriteLine("Network available");
}
else
{
Console.WriteLine("Network not available");
}
The program prints if a network is available. A network connection is considered available if any interface other than the loopback and tunnel interfaces is up. It does not mean that the internet is reachable.
$ dotnet run Network available
C# list network interfaces
In the following example, we list all active network interfaces.
using System.Net.NetworkInformation;
var nics = NetworkInterface.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == OperationalStatus.Up);
foreach (var nic in nics)
{
Console.WriteLine($"Name: {nic.Name}");
Console.WriteLine($"Description: {nic.Description}");
Console.WriteLine($"Type: {nic.NetworkInterfaceType}");
Console.WriteLine($"Status: {nic.OperationalStatus}");
Console.WriteLine($"Speed: {nic.Speed}");
Console.WriteLine("-----------------------------");
}
The GetAllNetworkInterfaces method returns objects that describe
the network interfaces on the local computer. We keep only the interfaces that
are up and print some of their properties.
$ dotnet run Name: lo Description: lo Type: Loopback Status: Up Speed: -1 ----------------------------- Name: wlp0s20f3 Description: wlp0s20f3 Type: Ethernet Status: Up Speed: -1 -----------------------------
The output depends on the operating system. On Linux, the description is the
same as the name, and wireless interfaces are reported as
Ethernet. The Speed property is given in bits per
second; -1 means that the speed is not known. On Windows, we get descriptive
names of the adapters and their speed.
C# NetworkInterface MAC address
A MAC address, also called a hardware or physical address, is a unique identifier that is used to identify individual devices on a local network.
using System.Net.NetworkInformation;
var nics = NetworkInterface.GetAllNetworkInterfaces()
.Where(nic => nic.NetworkInterfaceType != NetworkInterfaceType.Loopback
&& nic.OperationalStatus == OperationalStatus.Up);
foreach (var nic in nics)
{
PhysicalAddress mac = nic.GetPhysicalAddress();
string formatted = string.Join(":", mac.GetAddressBytes().Select(b => b.ToString("X2")));
Console.WriteLine($"{nic.Name}: {mac} {formatted}");
}
We retrieve the MAC address with the GetPhysicalAddress method. We
skip the loopback interface, which has no MAC address.
string formatted = string.Join(":", mac.GetAddressBytes().Select(b => b.ToString("X2")));
The ToString method of the PhysicalAddress prints the
bytes without separators. We format the address in the usual way with
colons between the bytes.
$ dotnet run wlp0s20f3: 001A2B3C4D5E 00:1A:2B:3C:4D:5E
C# NetworkInterface IP properties
The GetIPProperties method returns an object that provides
information about the IPv4 and IPv6 configuration of the interface: its
addresses, DNS servers, and gateways.
using System.Net.NetworkInformation;
using System.Net.Sockets;
var nic = NetworkInterface.GetAllNetworkInterfaces()
.FirstOrDefault(nic => nic.OperationalStatus == OperationalStatus.Up
&& nic.NetworkInterfaceType != NetworkInterfaceType.Loopback
&& nic.GetIPProperties().GatewayAddresses.Count > 0);
if (nic is null)
{
Console.WriteLine("no connected network interface found");
return;
}
IPInterfaceProperties ipProps = nic.GetIPProperties();
Console.WriteLine($"Interface: {nic.Name}");
Console.WriteLine("-----------------------------------");
foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses)
{
if (addr.Address.AddressFamily == AddressFamily.InterNetwork)
{
Console.WriteLine($"IPv4: {addr.Address}/{addr.PrefixLength} mask {addr.IPv4Mask}");
}
else
{
Console.WriteLine($"IPv6: {addr.Address}/{addr.PrefixLength}");
}
}
Console.WriteLine("-----------------------------------");
Console.WriteLine($"DNS suffix: {ipProps.DnsSuffix}");
Console.WriteLine($"DNS servers: {string.Join(", ", ipProps.DnsAddresses)}");
Console.WriteLine("-----------------------------------");
foreach (GatewayIPAddressInformation gw in ipProps.GatewayAddresses)
{
Console.WriteLine($"Gateway: {gw.Address}");
}
The example prints the IP addresses, DNS, and gateway information of the interface that connects us to the network.
var nic = NetworkInterface.GetAllNetworkInterfaces()
.FirstOrDefault(nic => nic.OperationalStatus == OperationalStatus.Up
&& nic.NetworkInterfaceType != NetworkInterfaceType.Loopback
&& nic.GetIPProperties().GatewayAddresses.Count > 0);
We pick the first active interface with a gateway. This skips virtual interfaces, such as Docker bridges, which are up but do not lead to other networks.
foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses)
{
if (addr.Address.AddressFamily == AddressFamily.InterNetwork)
{
Console.WriteLine($"IPv4: {addr.Address}/{addr.PrefixLength} mask {addr.IPv4Mask}");
}
else
{
Console.WriteLine($"IPv6: {addr.Address}/{addr.PrefixLength}");
}
}
An interface often has several addresses. We tell IPv4 and IPv6 addresses
apart by their address family. The network mask is meaningful only for IPv4
addresses; for both families, the PrefixLength gives the number of
bits of the network part.
$ dotnet run Interface: wlp0s20f3 ----------------------------------- IPv4: 192.168.0.35/24 mask 255.255.255.0 IPv6: 2001:db8:1:2::35/64 IPv6: fe80::1c3b:5e0c:5371:bddc%2/64 ----------------------------------- DNS suffix: . DNS servers: 127.0.0.53 ----------------------------------- Gateway: 192.168.0.1 Gateway: fe80::20b:ff:fe00:add0%2
On Ubuntu, the DNS server is 127.0.0.53, which is the local
resolver of systemd-resolved.
C# NetworkInterface IP statistics
With the GetIPStatistics method, we can get IP statistical data
for a network interface on the local computer.
using System.Net.NetworkInformation;
var nics = NetworkInterface.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == OperationalStatus.Up);
foreach (var nic in nics)
{
IPInterfaceStatistics stats = nic.GetIPStatistics();
Console.WriteLine(nic.Name);
Console.WriteLine($" Bytes received: {stats.BytesReceived:N0}");
Console.WriteLine($" Bytes sent: {stats.BytesSent:N0}");
Console.WriteLine($" Incoming packets with errors: {stats.IncomingPacketsWithErrors}");
Console.WriteLine($" Outgoing packets with errors: {stats.OutgoingPacketsWithErrors}");
Console.WriteLine($" Incoming packets discarded: {stats.IncomingPacketsDiscarded}");
Console.WriteLine($" Outgoing packets discarded: {stats.OutgoingPacketsDiscarded}");
}
The example prints the number of bytes received and sent and the number of packets with errors and packets discarded for each active interface. The counters are cumulative since the interface was brought up.
Not all statistics are available on all platforms. For instance, the
OutgoingPacketsDiscarded property is not supported on macOS; the
compiler's platform compatibility analyzer reports this with the
CA1416 warning.
$ dotnet run lo Bytes received: 387,837 Bytes sent: 387,837 Incoming packets with errors: 0 Outgoing packets with errors: 0 Incoming packets discarded: 0 Outgoing packets discarded: 0 wlp0s20f3 Bytes received: 352,919,722 Bytes sent: 12,808,662 Incoming packets with errors: 0 Outgoing packets with errors: 0 Incoming packets discarded: 0 Outgoing packets discarded: 0
C# IPGlobalProperties
The IPGlobalProperties class provides information about the
network connectivity of the whole computer, not of a single interface. We can
get the active TCP connections and listeners, UDP listeners, and protocol
statistics.
using System.Net.NetworkInformation;
IPGlobalProperties props = IPGlobalProperties.GetIPGlobalProperties();
Console.WriteLine($"Host name: {props.HostName}");
Console.WriteLine("Listening TCP ports:");
var ports = props.GetActiveTcpListeners()
.Select(ep => ep.Port)
.Distinct()
.Order();
Console.WriteLine(string.Join(", ", ports));
Console.WriteLine("Established TCP connections:");
var connections = props.GetActiveTcpConnections()
.Where(c => c.State == TcpState.Established);
foreach (TcpConnectionInformation c in connections)
{
Console.WriteLine($"{c.LocalEndPoint} -> {c.RemoteEndPoint}");
}
The program lists the TCP ports on which the local services listen and the
established TCP connections, similar to the netstat or
ss tools.
var ports = props.GetActiveTcpListeners()
.Select(ep => ep.Port)
.Distinct()
.Order();
A service often listens on both IPv4 and IPv6 addresses, so we remove the duplicate port numbers and sort them.
$ dotnet run Host name: universum Listening TCP ports: 53, 80, 631, 3389, 5432, 6379 Established TCP connections: 192.168.0.35:33332 -> 93.184.215.14:443 192.168.0.35:40086 -> 172.67.68.208:443 ...
C# NetworkChange
The NetworkChange class raises events when the network
configuration changes: the NetworkAvailabilityChanged event when
the network becomes available or unavailable, and the
NetworkAddressChanged event when an IP address of an interface
changes, for instance when Wi-Fi reconnects or a VPN starts.
using System.Net.NetworkInformation;
using System.Net.Sockets;
NetworkChange.NetworkAvailabilityChanged += (_, e) =>
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss} network available: {e.IsAvailable}");
};
NetworkChange.NetworkAddressChanged += (_, _) =>
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss} network addresses changed");
PrintAddresses();
};
PrintAddresses();
Console.WriteLine("Watching for network changes; press Enter to quit");
Console.ReadLine();
static void PrintAddresses()
{
var nics = NetworkInterface.GetAllNetworkInterfaces()
.Where(nic => nic.OperationalStatus == OperationalStatus.Up);
foreach (var nic in nics)
{
var ipv4 = nic.GetIPProperties().UnicastAddresses
.Where(a => a.Address.AddressFamily == AddressFamily.InterNetwork)
.Select(a => $"{a.Address}/{a.PrefixLength}");
Console.WriteLine($" {nic.Name}: {string.Join(", ", ipv4)}");
}
}
The program prints the IPv4 addresses of the active interfaces and prints them again whenever the addresses change.
NetworkChange.NetworkAddressChanged += (_, _) =>
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss} network addresses changed");
PrintAddresses();
};
The event does not say what has changed, so we query the interfaces again. The handlers run on a thread pool thread.
$ dotnet run lo: 127.0.0.1/8 wlp0s20f3: 192.168.0.35/24 Watching for network changes; press Enter to quit 19:25:40 network addresses changed lo: 127.0.0.1/8 wlp0s20f3: 192.168.0.35/24 19:25:40 network available: True 19:25:44 network addresses changed lo: 127.0.0.1/8 wlp0s20f3: 192.168.0.35/24 19:25:44 network available: True
To trigger the events, we created and removed a Docker network in another
terminal with docker network create test and
docker network rm test. Docker adds and removes a bridge
interface; the bridge has no connected containers, so it is not up and does
not appear in the list.
Source
NetworkInterface class - language reference
In this article we have worked with network interfaces in C#.
Author
List all C# tutorials.