ARPテーブルの取得 (C#)(F#)
ARPテーブル一覧は、iphlpapi.dllのGetIpNetTable()で取得できます。
サンプルは、コマンドラインから「arp -a」としたものと同じです。
C#サンプル
using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Linq; namespace Example { class Program { [DllImport("iphlpapi.dll")] extern static int GetIpNetTable(IntPtr pTcpTable, ref int pdwSize, bool bOrder); [StructLayout(LayoutKind.Sequential)] public struct MIB_IPNETROW { public int Index; public int PhysAddrLen; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] PhysAddr; public int Addr; public int Type; } static string[] typeStr = { "", "その他", "無効", "動的", "静的" }; static void Main(string[] args) { List<MIB_IPNETROW> ar = new List<MIB_IPNETROW>(); int size = 0; GetIpNetTable(IntPtr.Zero, ref size, true);//必要サイズの取得 var p = Marshal.AllocHGlobal(size);//メモリ割当て if (GetIpNetTable(p, ref size, true) == 0) {//データの取得 var num = Marshal.ReadInt32(p);//MIB_IPNETTABLE.dwNumEntries(データ数) var ptr = IntPtr.Add(p, 4); for (int i = 0; i < num; i++) { ar.Add((MIB_IPNETROW)Marshal.PtrToStructure(ptr, typeof(MIB_IPNETROW))); ptr = IntPtr.Add(ptr, Marshal.SizeOf(typeof(MIB_IPNETROW)));//次のデータ } Marshal.FreeHGlobal(p); //メモリ開放 } foreach (var i in ar.GroupBy(x => x.Index)) { Console.WriteLine(string.Format("nインターフェース:0x{0:x}", i.Key)); Console.WriteLine(" インターネット アドレスt物理アドレスt種類"); foreach (var n in ar.Where(x => x.Index == i.Key)) { Console.WriteLine(string.Format(" {0,-15}t{1}t{2}" ,ipstr(n.Addr) ,macstr(n.PhysAddr) ,typeStr[n.Type])); } } Console.WriteLine(); Console.WriteLine("何かのキーを押してください。"); Console.ReadKey(); } private static string macstr(byte[] m) { return string.Format("{0:x2}-{1:x2}-{2:x2}-{3:x2}-{4:x2}-{5:x2}", m[0], m[1], m[2], m[3], m[4], m[5]); } private static string ipstr(int addr) { var b = BitConverter.GetBytes(addr); return string.Format("{0}.{1}.{2}.{3}", b[0], b[1], b[2], b[3]); } } }
F#サンプル
open System open System.Runtime.InteropServices open System.Collections.Generic open System.Linq [<DllImport("iphlpapi.dll")>] extern int GetIpNetTable(IntPtr pTcpTable, int *pdwSize, bool bOrder); [<Struct; StructLayout(LayoutKind.Sequential)>] type MIB_IPNETROW = val Index:int val PhysAddrLen:int [<MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)>] val PhysAddr:byte [] val Addr:int val Type:int let ipstr(addr:int)= let b = BitConverter.GetBytes(addr) sprintf "%d.%d.%d.%d" b.[0] b.[1] b.[2] b.[3] let macstr(m:byte []) = sprintf "%02x-%02x-%02x-%02x-%02x-%02x" m.[0] m.[1] m.[2] m.[3] m.[4] m.[5] let typeStr = ["";"その他";"無効";"動的";"静的"] let mutable ar = [] printfn "インデックスtインターネット アドレスt物理アドレスt種類" let mutable size = 0 GetIpNetTable(IntPtr.Zero,&&size, true)|>ignore//必要サイズの取得 let p = Marshal.AllocHGlobal(size)//メモリ割当て if GetIpNetTable(p, &&size, true) = 0 then //データの取得 let num = Marshal.ReadInt32(p)//MIB_IPNETTABLE.dwNumEntries(データ数) let mutable ptr = IntPtr.Add(p, 4) for i in [0..num-1] do ar <- ar @ [Marshal.PtrToStructure(ptr,typeof<MIB_IPNETROW>):?>MIB_IPNETROW] ptr <- IntPtr.Add(ptr, Marshal.SizeOf(typeof<MIB_IPNETROW>))//次のデータ Marshal.FreeHGlobal(p) //メモリ開放 for i in ar.GroupBy( fun n -> n.Index) do printfn "nインターフェース:0x%x" i.Key printfn " インターネット アドレスt物理アドレスt種類" for n in ar.Where(fun (x:MIB_IPNETROW) -> x.Index=i.Key) do printfn " %-15st%st%s" (ipstr(n.Addr)) (macstr(n.PhysAddr)) (typeStr.[n.Type]) printfn "何かのキーを押してください。" Console.ReadKey() |> ignore
もう少し、進歩できないかと思い始めています・・・・
zeclさん、mclh46さん もっとF#らしい書き方があったら、ぜひ教えてやってください。
「っと、何気なくここに書いてみるテスト」