TCPコネクションの一覧取得 (C#)(F#)
TCPコネクションの一覧は、iphlpapi.dllのGetTcpTable()で取得することが可能です。
GetTcpTable()で取得するデータサイズは、最初にnullを指定して確認します。
コマンドラインから「netstat -an -p TCP」としたときの出力と同じものです。
C#サンプル
using System; using System.Runtime.InteropServices; namespace Exsample { class Program { [DllImport("iphlpapi.dll")] extern static int GetTcpTable(IntPtr pTcpTable, ref int pdwSize, bool bOrder); [StructLayout(LayoutKind.Sequential)] public struct MIB_TCPROW { public int State; public int LocalAddr; public int LocalPort; public int RemoteAddr; public int RemotePort; } public static string[] StateStrings = { "", "CLOSED","LISTENING","SYN_SENT","SYN_RCVD","ESTABLISHED","FIN_WAIT1", "FIN_WAIT2","CLOSE_WAIT","CLOSING","LAST_ACK","TIME_WAIT","DELETE_TCB"}; static void Main(string[] args) { Console.WriteLine("プロトコルtローカルアドレスt外部アドレスt状態"); var size = 0; GetTcpTable(IntPtr.Zero, ref size, false);//必要サイズの取得 var p = Marshal.AllocHGlobal(size);//メモリ割当て if (GetTcpTable(p, ref size, true) == 0) {//TCPテーブルの取得 var num = Marshal.ReadInt32(p);//MIB_TCPTABLE.dwNumEntries(データ数) var ptr = IntPtr.Add(p, 4); for (int i = 0; i < num; i++) { var o = (MIB_TCPROW)Marshal.PtrToStructure(ptr, typeof(MIB_TCPROW)); if (o.RemoteAddr == 0) o.RemotePort = 0;//RemoteAddrが0の場合は、RemotePortも0にする Console.WriteLine(string.Format("TCPt{0}:{1}t{2}:{3}t{4}" , ipstr(o.LocalAddr),htons(o.LocalPort) , ipstr(o.RemoteAddr),htons(o.RemotePort) , StateStrings[o.State])); ptr = IntPtr.Add(ptr, Marshal.SizeOf(typeof(MIB_TCPROW)));//次のデータ } Marshal.FreeHGlobal(p); //メモリ開放 } Console.WriteLine(); Console.WriteLine("何かのキーを押してください。"); Console.ReadKey(); } 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]); } public static int htons(int i) { var tmp = (((0x000000ff&i) << 8) + ((0x0000ff00&i) >> 8)) + ((0x00ff0000&i)<<8) + ((0xff000000&i)>>8); return (int)tmp; } } }
F#サンプル
open System open System.Runtime.InteropServices let ipstr(addr:int)= let b = BitConverter.GetBytes(addr) sprintf "%d.%d.%d.%d" b.[0] b.[1] b.[2] b.[3] let htons(i) = (((0x000000ff&&&i) <<< 8) + ((0x0000ff00&&&i) >>> 8)) + ((0x00ff0000&&&i)<<<8) + ((0xff000000&&&i)>>>8) [<DllImport("iphlpapi.dll")>] extern int GetTcpTable(IntPtr pTcpTable,int *pdwSize,bool bOrder) [<StructLayout(LayoutKind.Sequential)>] type MIB_TCPROW = struct val State : int val LocalAddr : int val LocalPort : int val RemoteAddr: int val mutable RemotePort: int end let StateStrings = [ ""; "CLOSED";"LISTENING";"SYN_SENT";"SYN_RCVD";"ESTABLISHED";"FIN_WAIT1"; "FIN_WAIT2";"CLOSE_WAIT";"CLOSING";"LAST_ACK";"TIME_WAIT";"DELETE_TCB"] printfn "プロトコルtローカルアドレスt外部アドレスt状態" let mutable size = 0 GetTcpTable(IntPtr.Zero,&&size,false)//必要サイズの取得 let p = Marshal.AllocHGlobal(size)//メモリ割当て if GetTcpTable(p, &&size, true) = 0 then //TCPテーブルの取得 let num = Marshal.ReadInt32(p)//MIB_TCPTABLE.dwNumEntries(データ数) let mutable ptr = IntPtr.Add(p,4) for i in [0..num-1] do let mutable o = Marshal.PtrToStructure(ptr, typeof<MIB_TCPROW>):?>MIB_TCPROW if o.RemoteAddr=0 then o.RemotePort<-0//RemoteAddrが0の場合は、RemotePortも0にする printfn "TCPt%s:%dt%s:%dt%s" (ipstr(o.LocalAddr)) (htons(o.LocalPort)) (ipstr(o.RemoteAddr)) (htons(o.RemotePort)) (StateStrings.[o.State]) ptr <- IntPtr.Add(ptr, Marshal.SizeOf(typeof<MIB_TCPROW>))//次のデータ Marshal.FreeHGlobal(p); //メモリ開放 printfn "" printfn "何かのキーを押してください。" Console.ReadKey() |> ignore