Hello,
I am trying to get network statistics using Swift on macOS. I am attempting to obtain:
- total input bytes
- total output bytes
- total input packets
- total output packets
The following code works in the app as far as I can tell so far, but... the for-loop is a hack that I'd like to correct by properly iterating over all the interfaces.
import Foundation
import OSLog
struct NetworkStatisticsData {
var totalInputBytes: UInt64 = 0
var totalOutputBytes: UInt64 = 0
var totalInputPackets: UInt64 = 0
var totalOutputPackets: UInt64 = 0
}
final class NetworkStatistics: Sendable {
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!,
category: "SwiftNetworkInformation")
func getNetworkStatistics() -> NetworkStatisticsData {
var networkStatisticsData = NetworkStatisticsData()
for i in 1..<24 { // <- this for-loop should be iterating over a list of interfaces. NET_RT_IFLIST2 ?
var keys: [Int32] = [ CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, Int32(i), IFDATA_GENERAL ]
var mibData: ifmibdata = ifmibdata()
var mibDataSize: size_t = MemoryLayout<ifmibdata>.size
if sysctl(&keys, u_int(keys.count), &mibData, &mibDataSize, nil, 0) < 0 {
logger.error("sysctl error getting mib data: \(String(describing: strerror(errno)))")
}
networkStatisticsData.totalInputPackets += mibData.ifmd_data.ifi_ipackets
networkStatisticsData.totalOutputPackets += mibData.ifmd_data.ifi_opackets
networkStatisticsData.totalInputBytes += mibData.ifmd_data.ifi_ibytes
networkStatisticsData.totalOutputBytes += mibData.ifmd_data.ifi_obytes
}
return networkStatisticsData
}
}
Any thoughts on how to iterate over all of the network interfaces (maybe using NET_RT_IFLIST2)? When I run ifconfig in the terminal, there are 24 interfaces, hence the reason for 24 in the for-loop.
I have some general background to this in the Network Interface Statistics post hanging off Extra-ordinary Networking. That post also has links to other posts about iterating the interface list.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"