网络数据包监视 - 类
来源:互联网 发布:淘宝达人是什么 编辑:程序博客网 时间:2024/05/18 12:35
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
namespace 网络数据包监视
{
public class PacketArrivedEventArgs
{
public uint HeaderLength; // = (uint)(head->ip_verlen & 0x0F) << 2;
public string Protocol; // = "ICMP"; break;
public string IPVersion; //= temp_version.ToString();
public string DestinationAddress; // = temp_ip.ToString();
public string OriginationPort; // = IPAddress.NetworkToHostOrder(temp_srcport).ToString();
public string DestinationPort; // = IPAddress.NetworkToHostOrder(temp_dstport).ToString();
public uint PacketLength; // = (uint)len;
public uint MessageLength; // = (uint)len - e.HeaderLength;
public byte[] ReceiveBuffer; // = buf;
public byte[] IPHeaderBuffer;
public string OriginationAddress;
public byte[] MessageBuffer;
public PacketArrivedEventArgs()
{
}
}
public delegate void ReceiveData (byte[] receive_buf_bytes, int received_bytes);
public class RowSocket
{
//事件句柄:包到达时引发事件
public event PacketArrivedEventHandler OnPacketArrival;//声明时间句柄函数
public RowSocket() //构造函数
{
error_occurred = false;
len_receive_buf = 4096;
receive_buf_bytes = new byte[len_receive_buf];
}
[StructLayout(LayoutKind.Explicit)]
public struct IPHeader
{
[FieldOffset(0)]
public byte ip_verlen; //I4位首部长度+4位IP版本号
[FieldOffset(1)]
public byte ip_tos; //8位服务类型TOS
[FieldOffset(2)]
public ushort ip_totallength; //16位数据包总长度(字节)
[FieldOffset(4)]
public ushort ip_id; //16位标识
[FieldOffset(6)]
public ushort ip_offset; //3位标志位
[FieldOffset(8)]
public byte ip_ttl; //8位生存时间 TTL
[FieldOffset(9)]
public byte ip_protocol; //8位协议(TCP, UDP, ICMP, Etc.)
[FieldOffset(10)]
public ushort ip_checksum; //16位IP首部校验和
[FieldOffset(12)]
public uint ip_srcaddr; //32位源IP地址
[FieldOffset(16)]
public uint ip_destaddr; //32位目的IP地址
}
public ReceiveData OnDataArrived;//
const int SIO_RCVALL = unchecked((int)0x98000001);//监听所有的数据包
private bool error_occurred; //套接字在接收包时是否产生错误
public bool KeepRunning; //是否继续进行
private static int len_receive_buf; //得到的数据流的长度
byte[] receive_buf_bytes; //收到的字节
private Socket socket = null; //声明套接字
public void CreateAndBindSocket(string IP) //建立并绑定套接字
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
socket.Blocking = false; //置socket非阻塞状态
socket.Bind(new IPEndPoint(IPAddress.Parse(IP), 0)); //绑定套接字
if (SetSocketOption() == false) error_occurred = true;
}
private bool SetSocketOption() //设置raw socket
{
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];
//低级别操作模式,接受所有的数据包,这一步是关键,必须把socket设成raw和IP Level才可用SIO_RCVALL
int ret_code = socket.IOControl(SIO_RCVALL, IN, OUT);
ret_code = OUT[0] + OUT[1] + OUT[2] + OUT[3];//把4个8位字节合成一个32位整数
if (ret_code != 0) ret_value = false;
}
catch (SocketException)
{
ret_value = false;
}
return ret_value;
}
/*
int WSAIoctl(
SOCKET s, //一个指定的套接字
DWORD dwIoControlCode, //控制操作码
LPVOID lpvInBuffer, //指向输入数据流的指针
DWORD cbInBuffer, //输入数据流的大小(字节数)
LPVOID lpvOutBuffer, // 指向输出数据流的指针
DWORD cbOutBuffer, //输出数据流的大小(字节数)
LPDWORD lpcbBytesReturned, //指向输出字节流数目的实数值
LPWSAOVERLAPPED lpOverlapped, //指向一个WSAOVERLAPPED结构
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine//指向操作完成时执行的例程
);
*/
public bool ErrorOccurred
{
get
{
return error_occurred;
}
}
//解析接收的数据包,形成PacketArrivedEventArgs事件数据类对象,并引发PacketArrival事件
unsafe private void Receive(byte[] buf, int len)
{
byte temp_protocol = 0;
uint temp_version = 0;
uint temp_ip_srcaddr = 0;
uint temp_ip_destaddr = 0;
short temp_srcport = 0;
short temp_dstport = 0;
IPAddress temp_ip;
PacketArrivedEventArgs e = new PacketArrivedEventArgs();//新网络数据包信息事件
fixed (byte* fixed_buf = buf)
{
IPHeader* head = (IPHeader*)fixed_buf;//把数据流整和为IPHeader结构
e.HeaderLength = (uint)(head->ip_verlen & 0x0F) << 2;
temp_protocol = head->ip_protocol;
switch (temp_protocol)//提取协议类型
{
case 1: e.Protocol = "ICMP"; break;
case 2: e.Protocol = "IGMP"; break;
case 6: e.Protocol = "TCP"; break;
case 17: e.Protocol = "UDP"; break;
default: e.Protocol = "UNKNOWN"; break;
}
temp_version = (uint)(head->ip_verlen & 0xF0) >> 4;//提取IP协议版本
e.IPVersion = temp_version.ToString();
//以下语句提取出了PacketArrivedEventArgs对象中的其他参数
temp_ip_srcaddr = head->ip_srcaddr;
temp_ip_destaddr = head->ip_destaddr;
temp_ip = new IPAddress(temp_ip_srcaddr);
e.OriginationAddress = temp_ip.ToString();
temp_ip = new IPAddress(temp_ip_destaddr);
e.DestinationAddress = temp_ip.ToString();
temp_srcport = *(short*)&fixed_buf[e.HeaderLength];
temp_dstport = *(short*)&fixed_buf[e.HeaderLength + 2];
e.OriginationPort = IPAddress.NetworkToHostOrder(temp_srcport).ToString();
e.DestinationPort = IPAddress.NetworkToHostOrder(temp_dstport).ToString();
e.PacketLength = (uint)len;
e.MessageLength = (uint)len - e.HeaderLength;
e.ReceiveBuffer = buf;
e.IPHeaderBuffer = new byte[e.HeaderLength];
//把buf中的IP头赋给PacketArrivedEventArgs中的IPHeaderBuffer
Array.Copy(buf, 0, e.IPHeaderBuffer, 0, (int)e.HeaderLength);
//把buf中的包中内容赋给PacketArrivedEventArgs中的MessageBuffer
e.MessageBuffer = new byte[e.MessageLength];
Array.Copy(buf, (int)e.HeaderLength, e.MessageBuffer, 0, (int)e.MessageLength);
}
//引发PacketArrival事件
if (OnPacketArrival != null)
OnPacketArrival(this, e);
}
public void Run() //开始监听
{
IAsyncResult ar = socket.BeginReceive(receive_buf_bytes, 0, len_receive_buf, SocketFlags.None, new AsyncCallback(CallReceive), this);
}
private void CallReceive(IAsyncResult ar)//异步回调
{
int received_bytes;
received_bytes = socket.EndReceive(ar);
Receive(receive_buf_bytes, received_bytes);
//OnPacketArrival(e);
//OnDataArrived(receive_buf_bytes, received_bytes);
if (KeepRunning) Run();
}
public delegate void PacketArrivedEventHandler(Object sender, PacketArrivedEventArgs args);
public void Close() //关闭raw socket
{
if (socket != null)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
}
}
用法:
RowSocket rs;
rs = new RowSocket();
rs.OnPacketArrival += new RowSocket.PacketArrivedEventHandler(rs_OnPacketArrival);
rs.CreateAndBindSocket("10.32.32.52");
rs.KeepRunning = true;
rs.Run();
更多黄瑞杰的文章
- 网络数据包监视 - 类
- 网络数据包监视程序开发日志(三)
- 网络数据包监视程序开发日志(四)
- 网络数据包监视程序开发日志(五)
- 网络数据包监视程序开发(七)
- 网络数据包监视程序开发(八)
- 网络数据包监视程序开发(九)
- 网络数据包监视程序开发日志(一)
- 网络数据包监视程序开发日志(二)
- 网络数据包监视程序开发(六)--QQ登录过程
- 网络数据包监视程序开发(十一)---ARP欺骗
- 网络数据包监视程序开发(十三)---QQ密码加密方式
- 网络数据包监视程序开发(十四)---毕设结束了
- 网络数据包监视程序开发(十)---截取指定网段的数据包
- 网络数据包监视程序开发(十二)---Windows下启用IP路由选择
- linux命令之----tcpdump用于截取或监视网络传输的数据包
- 另类挂钩-RING3数据包监视
- 另类挂钩 RING3数据包监视
- 有关注册DataItem的一些可能被忽视的事情 VS System.Web.UI.ScriptManager.RegisterStartupScript
- MFC对文件的操作
- Machine.Config Web.Config及配置文件层次结构和继承(转载)
- struts+spring+hibernate的web应用 Web层代码编写(1)
- cvs [login aborted]: lrj: no such user
- 网络数据包监视 - 类
- 一招让你winXP右下角显示星期几
- struts+spring+hibernate的web应用 Web层代码编写(2)
- 关于数据库的一道题??
- 再次遇到CSDN blog无法发表的bug
- 互联网产品,如何作?
- JSP安全编程实例浅析
- Struts2.0+spring2.0+hibernate3.1升级体会
- 老徐的一篇文章,符合我现在的心情,收藏一下