Click here to Skip to main content
15,881,938 members
Articles / Desktop Programming / MFC

Getting active TCP/UDP connections on a box

Rate me:
Please Sign up or sign in to vote.
4.81/5 (37 votes)
17 Jun 20037 min read 323.5K   11.5K   99  
This article shows an implementation of the main TCP/UDP functions of the IP Helper API that is used to get info about active connections including the process attached to a connection
using System;
using System.Net;
using System.Text;
using System.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace IpHlpApidotnet
{
	public class IPHelper
	{
		private const int NO_ERROR  = 0;
		private const int MIB_TCP_STATE_CLOSED = 1;
		private const int MIB_TCP_STATE_LISTEN = 2;
		private const int MIB_TCP_STATE_SYN_SENT = 3;
		private const int MIB_TCP_STATE_SYN_RCVD = 4;
		private const int MIB_TCP_STATE_ESTAB = 5;
		private const int MIB_TCP_STATE_FIN_WAIT1 = 6;
		private const int MIB_TCP_STATE_FIN_WAIT2 = 7;
		private const int MIB_TCP_STATE_CLOSE_WAIT = 8;
		private const int MIB_TCP_STATE_CLOSING = 9;
		private const int MIB_TCP_STATE_LAST_ACK = 10;
		private const int MIB_TCP_STATE_TIME_WAIT = 11;
		private const int MIB_TCP_STATE_DELETE_TCB = 12;

		

		
		/*
		 * Tcp Struct
		 * */

		public IpHlpApidotnet.MIB_TCPTABLE TcpConnexion;
		public IpHlpApidotnet.MIB_TCPSTATS TcpStats;
		public IpHlpApidotnet.MIB_EXTCPTABLE TcpExConnexions;
		

		/*
		 * Udp Struct
		 * */
		public IpHlpApidotnet.MIB_UDPSTATS UdpStats;
		public IpHlpApidotnet.MIB_UDPTABLE UdpConnexion;
		public IpHlpApidotnet.MIB_EXUDPTABLE UdpExConnexion;
		



		
		
		public IPHelper()
		{
		
		}

		
		#region Tcp Function

		public void GetTcpStats()
		{
			TcpStats = new MIB_TCPSTATS();
			IPHlpAPI32Wrapper.GetTcpStatistics(ref TcpStats);
		}


		public void GetExTcpConnexions()
		{
			
			// the size of the MIB_EXTCPROW struct =  6*DWORD
			int rowsize = 24;
			int BufferSize = 100000;
			// allocate a dumb memory space in order to retrieve  nb of connexion
			IntPtr lpTable = Marshal.AllocHGlobal(BufferSize);
			//getting infos
			int res = IPHlpAPI32Wrapper.AllocateAndGetTcpExTableFromStack(ref lpTable, true, IPHlpAPI32Wrapper.GetProcessHeap(),0,2);
			if(res!=NO_ERROR)
			{
				Debug.WriteLine("Erreur : "+IPHlpAPI32Wrapper.GetAPIErrorMessageDescription(res)+" "+res);
				return; // Error. You should handle it
			}
			int CurrentIndex = 0;
			//get the number of entries in the table
			int NumEntries= (int)Marshal.ReadIntPtr(lpTable);
			lpTable = IntPtr.Zero;
			// free allocated space in memory
			Marshal.FreeHGlobal(lpTable);



			///////////////////
			// calculate the real buffer size nb of entrie * size of the struct for each entrie(24) + the dwNumEntries
			BufferSize = (NumEntries*rowsize)+4;
			// make the struct to hold the resullts
			TcpExConnexions = new IpHlpApidotnet.MIB_EXTCPTABLE();
			// Allocate memory
			lpTable = Marshal.AllocHGlobal(BufferSize);
			res = IPHlpAPI32Wrapper.AllocateAndGetTcpExTableFromStack(ref lpTable, true,IPHlpAPI32Wrapper.GetProcessHeap() ,0,2);
			if(res!=NO_ERROR)
			{
				Debug.WriteLine("Erreur : "+IPHlpAPI32Wrapper.GetAPIErrorMessageDescription(res)+" "+res);
				return; // Error. You should handle it
			}
			// New pointer of iterating throught the data
			IntPtr current = lpTable;
			CurrentIndex = 0;
			// get the (again) the number of entries
			NumEntries = (int)Marshal.ReadIntPtr(current);
			TcpExConnexions.dwNumEntries = 	NumEntries;
			// Make the array of entries
			TcpExConnexions.table = new MIB_EXTCPROW[NumEntries];
			// iterate the pointer of 4 (the size of the DWORD dwNumEntries)
			CurrentIndex+=4;
			current = (IntPtr)((int)current+CurrentIndex);
			// for each entries
			for(int i=0; i< NumEntries;i++)
			{
				
				// The state of the connexion (in string)
				TcpExConnexions.table[i].StrgState = this.convert_state((int)Marshal.ReadIntPtr(current));
				// The state of the connexion (in ID)
				TcpExConnexions.table[i].iState = (int)Marshal.ReadIntPtr(current);
				// iterate the pointer of 4
				current = (IntPtr)((int)current+4);
				// get the local address of the connexion
				UInt32 localAddr = (UInt32)Marshal.ReadIntPtr(current);
				// iterate the pointer of 4
				current = (IntPtr)((int)current+4);
				// get the local port of the connexion
				UInt32 localPort = (UInt32)Marshal.ReadIntPtr(current);
				// iterate the pointer of 4
				current = (IntPtr)((int)current+4);
				// Store the local endpoint in the struct and convertthe port in decimal (ie convert_Port())
				TcpExConnexions.table[i].Local = new IPEndPoint(localAddr,(int)convert_Port(localPort));
				// get the remote address of the connexion
				UInt32 RemoteAddr = (UInt32)Marshal.ReadIntPtr(current);
				// iterate the pointer of 4
				current = (IntPtr)((int)current+4);
				UInt32 RemotePort=0;
				// if the remote address = 0 (0.0.0.0) the remote port is always 0
				// else get the remote port
				if(RemoteAddr!=0)
				{
					RemotePort = (UInt32)Marshal.ReadIntPtr(current);
					RemotePort=convert_Port(RemotePort);
				}
				current = (IntPtr)((int)current+4);
				// store the remote endpoint in the struct  and convertthe port in decimal (ie convert_Port())
				TcpExConnexions.table[i].Remote = new IPEndPoint(RemoteAddr,(int)RemotePort);
				// store the process ID
				TcpExConnexions.table[i].dwProcessId = (int)Marshal.ReadIntPtr(current);
				// Store and get the process name in the struct
				TcpExConnexions.table[i].ProcessName = this.get_process_name(TcpExConnexions.table[i].dwProcessId);
				current = (IntPtr)((int)current+4);
		
			}
			// free the buffer
			Marshal.FreeHGlobal(lpTable);
			// re init the pointer
			current = IntPtr.Zero;
		}


		public void GetTcpConnexions()
		{
			byte[] buffer = new byte[20000]; // Start with 20.000 bytes left for information about tcp table
			int pdwSize = 20000;
			int res = IPHlpAPI32Wrapper.GetTcpTable(buffer, out pdwSize, true);
			if (res != NO_ERROR)
			{
				buffer = new byte[pdwSize];
				res = IPHlpAPI32Wrapper.GetTcpTable(buffer, out pdwSize, true);
				if (res != 0)
					return;     // Error. You should handle it
			}
			
			TcpConnexion = new IpHlpApidotnet.MIB_TCPTABLE();

			int nOffset = 0;
			// number of entry in the
			TcpConnexion.dwNumEntries = Convert.ToInt32(buffer[nOffset]);
			nOffset+=4; 
			TcpConnexion.table = new MIB_TCPROW[TcpConnexion.dwNumEntries];

			for(int i=0; i<TcpConnexion.dwNumEntries;i++)
			{
				// state
				int st = Convert.ToInt32(buffer[nOffset]);
				// state in string
				((MIB_TCPROW)(TcpConnexion.table[i])).StrgState=convert_state(st);
				// state  by ID
				((MIB_TCPROW)(TcpConnexion.table[i])).iState = st;
				nOffset+=4; 
				// local address
				string LocalAdrr = buffer[nOffset].ToString()+"."+buffer[nOffset+1].ToString()+"."+buffer[nOffset+2].ToString()+"."+buffer[nOffset+3].ToString();
				nOffset+=4; 
				//local port in decimal
				int LocalPort = (((int)buffer[nOffset])<<8) + (((int)buffer[nOffset+1])) + 
					(((int)buffer[nOffset+2])<<24) + (((int)buffer[nOffset+3])<<16);

				nOffset+=4; 
				// store the remote endpoint
				((MIB_TCPROW)(TcpConnexion.table[i])).Local = new IPEndPoint(IPAddress.Parse(LocalAdrr),LocalPort);

				// remote address
				string RemoteAdrr = buffer[nOffset].ToString()+"."+buffer[nOffset+1].ToString()+"."+buffer[nOffset+2].ToString()+"."+buffer[nOffset+3].ToString();
				nOffset+=4; 
				// if the remote address = 0 (0.0.0.0) the remote port is always 0
				// else get the remote port in decimal
				int RemotePort;
				//
				if(RemoteAdrr == "0.0.0.0")
				{
					RemotePort = 0;
				}
				else
				{
					RemotePort = (((int)buffer[nOffset])<<8) + (((int)buffer[nOffset+1])) + 
						(((int)buffer[nOffset+2])<<24) + (((int)buffer[nOffset+3])<<16);
				}
				nOffset+=4; 
				((MIB_TCPROW)(TcpConnexion.table[i])).Remote = new IPEndPoint(IPAddress.Parse(RemoteAdrr),RemotePort);
			}
		}


		#endregion

		#region Udp Functions

		public void GetUdpStats()
		{
			
			UdpStats = new MIB_UDPSTATS();
			IPHlpAPI32Wrapper.GetUdpStatistics(ref UdpStats);
		}


		public void GetUdpConnexions()
		{
			byte[] buffer = new byte[20000]; // Start with 20.000 bytes left for information about tcp table
			int pdwSize = 20000;
			int res = IPHlpAPI32Wrapper.GetUdpTable(buffer, out pdwSize, true);
			if (res != NO_ERROR)
			{
				buffer = new byte[pdwSize];
				res = IPHlpAPI32Wrapper.GetUdpTable(buffer, out pdwSize, true);
				if (res != 0)
					return;     // Error. You should handle it
			}

			UdpConnexion = new IpHlpApidotnet.MIB_UDPTABLE();

			int nOffset = 0;
			// number of entry in the
			UdpConnexion.dwNumEntries = Convert.ToInt32(buffer[nOffset]);
			nOffset+=4; 
			UdpConnexion.table = new MIB_UDPROW[UdpConnexion.dwNumEntries];
			for(int i=0; i<UdpConnexion.dwNumEntries;i++)
			{
				string LocalAdrr = buffer[nOffset].ToString()+"."+buffer[nOffset+1].ToString()+"."+buffer[nOffset+2].ToString()+"."+buffer[nOffset+3].ToString();
				nOffset+=4; 

				int LocalPort = (((int)buffer[nOffset])<<8) + (((int)buffer[nOffset+1])) + 
					(((int)buffer[nOffset+2])<<24) + (((int)buffer[nOffset+3])<<16);
				nOffset+=4; 
				((MIB_UDPROW)(UdpConnexion.table[i])).Local = new IPEndPoint(IPAddress.Parse(LocalAdrr),LocalPort);
			}
		}


		public void GetExUdpConnexions()
		{
			
			// the size of the MIB_EXTCPROW struct =  4*DWORD
			int rowsize = 12;
			int BufferSize = 100000;
			// allocate a dumb memory space in order to retrieve  nb of connexion
			IntPtr lpTable = Marshal.AllocHGlobal(BufferSize);
			//getting infos
			int res = IPHlpAPI32Wrapper.AllocateAndGetUdpExTableFromStack(ref lpTable, true, IPHlpAPI32Wrapper.GetProcessHeap(),0,2);
			if(res!=NO_ERROR)
			{
				Debug.WriteLine("Erreur : "+IPHlpAPI32Wrapper.GetAPIErrorMessageDescription(res)+" "+res);
				return; // Error. You should handle it
			}
			int CurrentIndex = 0;
			//get the number of entries in the table
			int NumEntries= (int)Marshal.ReadIntPtr(lpTable);
			lpTable = IntPtr.Zero;
			// free allocated space in memory
			Marshal.FreeHGlobal(lpTable);
		
			///////////////////
			// calculate the real buffer size nb of entrie * size of the struct for each entrie(24) + the dwNumEntries
			BufferSize = (NumEntries*rowsize)+4;
			// make the struct to hold the resullts
			UdpExConnexion = new IpHlpApidotnet.MIB_EXUDPTABLE();
			// Allocate memory
			lpTable = Marshal.AllocHGlobal(BufferSize);
			res = IPHlpAPI32Wrapper.AllocateAndGetUdpExTableFromStack(ref lpTable, true,IPHlpAPI32Wrapper.GetProcessHeap() ,0,2);
			if(res!=NO_ERROR)
			{
				Debug.WriteLine("Erreur : "+IPHlpAPI32Wrapper.GetAPIErrorMessageDescription(res)+" "+res);
				return; // Error. You should handle it
			}
			// New pointer of iterating throught the data
			IntPtr current = lpTable;
			CurrentIndex = 0;
			// get the (again) the number of entries
			NumEntries = (int)Marshal.ReadIntPtr(current);
			UdpExConnexion.dwNumEntries = 	NumEntries;
			// Make the array of entries
			UdpExConnexion.table = new MIB_EXUDPROW[NumEntries];
			// iterate the pointer of 4 (the size of the DWORD dwNumEntries)
			CurrentIndex+=4;
			current = (IntPtr)((int)current+CurrentIndex);
			// for each entries
			for(int i=0; i< NumEntries;i++)
			{
				// get the local address of the connexion
				UInt32 localAddr = (UInt32)Marshal.ReadIntPtr(current);
				// iterate the pointer of 4
				current = (IntPtr)((int)current+4);
				// get the local port of the connexion
				UInt32 localPort = (UInt32)Marshal.ReadIntPtr(current);
				// iterate the pointer of 4
				current = (IntPtr)((int)current+4);
				// Store the local endpoint in the struct and convertthe port in decimal (ie convert_Port())
				UdpExConnexion.table[i].Local = new IPEndPoint(localAddr,convert_Port(localPort));
				// store the process ID
				UdpExConnexion.table[i].dwProcessId = (int)Marshal.ReadIntPtr(current);
				// Store and get the process name in the struct
				UdpExConnexion.table[i].ProcessName = this.get_process_name(UdpExConnexion.table[i].dwProcessId);
				current = (IntPtr)((int)current+4);
		
			}
			// free the buffer
			Marshal.FreeHGlobal(lpTable);
			// re init the pointer
			current = IntPtr.Zero;
		}


		#endregion

		#region helper fct

		private UInt16 convert_Port(UInt32 dwPort)
		{
			byte[] b = new Byte[2];
			// high weight byte
			b[0] = byte.Parse((dwPort>>8).ToString());
			// low weight byte
			b[1] = byte.Parse((dwPort & 0xFF).ToString());
			return BitConverter.ToUInt16(b,0);
		}


		private string convert_state(int state)
		{
			string strg_state="";
			switch(state)
			{
				case MIB_TCP_STATE_CLOSED: strg_state = "CLOSED" ;break;
				case MIB_TCP_STATE_LISTEN: strg_state = "LISTEN" ;break;
				case MIB_TCP_STATE_SYN_SENT: strg_state = "SYN_SENT" ;break;
				case MIB_TCP_STATE_SYN_RCVD: strg_state = "SYN_RCVD" ;break;
				case MIB_TCP_STATE_ESTAB: strg_state = "ESTAB" ;break;
				case MIB_TCP_STATE_FIN_WAIT1: strg_state = "FIN_WAIT1" ;break;
				case MIB_TCP_STATE_FIN_WAIT2: strg_state = "FIN_WAIT2" ;break;
				case MIB_TCP_STATE_CLOSE_WAIT: strg_state = "CLOSE_WAIT" ;break;
				case MIB_TCP_STATE_CLOSING: strg_state = "CLOSING" ;break;
				case MIB_TCP_STATE_LAST_ACK: strg_state = "LAST_ACK" ;break;
				case MIB_TCP_STATE_TIME_WAIT: strg_state = "TIME_WAIT" ;break;
				case MIB_TCP_STATE_DELETE_TCB: strg_state = "DELETE_TCB" ;break;
			}
			return strg_state;
		}


		private string get_process_name(int processID)
		{
			//could be an error here if the process die before we can get his name
			try
			{
				Process p = Process.GetProcessById((int)processID);
				return p.ProcessName;
			}
			catch(Exception ex)
			{
				Debug.WriteLine(ex.Message);
				return "unknown";
			}
				
		}


		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
France France
I am a software engineer in Paris, I have worked on several projects mostly database driven web site, and industrial application

I am also MCAD.NET
(70-316) "Developing Windows application with the Visual C# .NET"
(70-315) Developing and Implementing Web Applications with Microsoft® Visual C#™ .NET and Microsoft® Visual Studio® .NET
(70-320) Developing XML Web Services and Server Components with Microsoft Visual C# .NET and the Microsoft .NET Framework

Comments and Discussions