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
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);
}
}