Build your own network usage monitor in C# (raw socket)

Although there are lots of excellent network monitor available, e.g NetWorx, DU Meter, I just think to build my own network monitor. Firstly I can explore the socket programming, secondly it’s free of charge.

OK, let’s do it.

Create a new WinForm project from Visual Studio

Network monitor
Network monitor

 

 

 

 

public MainForm()
{
	//
	// Required for Windows Form Designer support
	//
	InitializeComponent();
	//
	// Set your PC ip address
	//
	rs.CreateAndBindSocket(ipaddress);
	rs.Run();
}
//when main window showing up, we update meter text
private void ShowMainWindow(object sender, System.EventArgs e)
{
	todayUsage.Text = string.Format("Today's Usage: {0}",FormatSize((ulong)rs.TotalReceivedBytes));	
}
//define ip header
[StructLayout(LayoutKind.Explicit)]  
public   struct   IPHeader  
{  
	[FieldOffset(0)]    public  byte       ip_verlen;    
	[FieldOffset(1)]    public  byte       ip_tos;    
	[FieldOffset(2)]    public  ushort     ip_totallength;  
	[FieldOffset(4)]    public  ushort     ip_id;  
	[FieldOffset(6)]    public  ushort     ip_offset;    
	[FieldOffset(8)]    public  byte       ip_ttl;    
	[FieldOffset(9)]    public  byte       ip_protocol;    
	[FieldOffset(10)]   public  ushort   ip_checksum;    
	[FieldOffset(12)]   public  uint       ip_srcaddr;    
	[FieldOffset(16)]   public  uint       ip_destaddr;    
}  
//the core function - raw socket   
public   class   RawSocket  
{
	private		bool	error_occurred;  
	private	  int	totalReceivedBytes = 0;
	private	  const   int   BUFFER_SIZE = 8192;
	private	  byte []	receive_buf = new byte[BUFFER_SIZE];
	private	  Socket	socket   =   null;    
	const	  int   SIO_R = unchecked((int)0x98000001);  
	const	  int   SIO_1 = unchecked((int)0x98000002);  
	const	  int   SIO_2 = unchecked((int)0x98000003);  

	public   int   TotalReceivedBytes
	{  
		get	{return   totalReceivedBytes;}  
		set	{totalReceivedBytes = value;}
	}

	public   RawSocket() 
	{  
		error_occurred=false;   
	}  
       
	public   void   CreateAndBindSocket(string   IP)
	{  
		socket   =   new   Socket(AddressFamily.InterNetwork,   SocketType.Raw,   ProtocolType.IP);  
		socket.Blocking   =   false; 
		socket.Bind(new   IPEndPoint(IPAddress.Parse(IP),   0));  
		if   (SetSocketOption()==false)   
			error_occurred=true;  
	}  
   
	public   bool   ErrorOccurred  
	{  
		get  { return   error_occurred;}  
	}

	public   void   Shutdown()  
	{  
		error_occurred = true;
		if(socket   !=   null)  
		{  
			socket.Shutdown(SocketShutdown.Both);  
			socket.Close();  
		}  
	}  
  
	private   bool   SetSocketOption()  
	{  
		bool   ret_value   =   true;  
		try  
		{  
			socket.SetSocketOption(SocketOptionLevel.IP,   SocketOptionName.HeaderIncluded,   1);       
			byte   []IN   =   new   byte[4]{1,   0,   0,   0};  
			byte   []OUT   =   new   byte[4];      
			int   ret_code   =   socket.IOControl(SIO_R,   IN,   OUT);
			ret_code   =   OUT[0]   +   OUT[1]   +   OUT[2]   +   OUT[3];   
			if(ret_code   !=   0)   ret_value   =   false;  
		}  
		catch(SocketException)  
		{  
			ret_value   =   false;  
		}  
		return   ret_value;  
	}

	unsafe   private   bool   IsInternetTraffic(byte[] buf)  
	{  
		byte	temp_protocol=0;  
		uint	temp_version=0;  
		uint	temp_ip_srcaddr=0;  
		string  sourceIP;  
  
		fixed(byte   *fixed_buf   =   buf)  
		{  
			IPHeader   *   head   =   (IPHeader   *)   fixed_buf;  
			temp_protocol   =   head->ip_protocol;  
			temp_version   =(uint)(head->ip_verlen   &   0xF0)   >>   4;  
			temp_ip_srcaddr   =   head->ip_srcaddr;  
			sourceIP   =   new   IPAddress(temp_ip_srcaddr).ToString();  
		}
                //we only capture internet traffic  
		return !sourceIP.StartsWith("10.") 
			&& !sourceIP.StartsWith("172.16.") 
			&& !sourceIP.StartsWith("127.") 
			&& !sourceIP.StartsWith("192.168.");
	}  
       
	private void ReceiveCallback( IAsyncResult ar)
	{
		try
		{
			int received_bytes = socket.EndReceive(ar);
			if(received_bytes>0 && IsInternetTraffic(receive_buf))
			{
				totalReceivedBytes += received_bytes;
			}
		}
		finally
		{
			socket.BeginReceive(receive_buf,0,BUFFER_SIZE,SocketFlags.None,new AsyncCallback(ReceiveCallback),null);
		}
	}
		
	public   void   Run()    
	{  
		socket.BeginReceive(receive_buf,0,BUFFER_SIZE,SocketFlags.None,new AsyncCallback(ReceiveCallback),null);
	}
}

2 thoughts on “Build your own network usage monitor in C# (raw socket)”

  1. Under InitComponts();

    whats this lines use object like "rs"

    rs.CreateAndBindSocket(ipaddress);
    rs.Run();

Leave a Reply

Your email address will not be published.