这几天参考网上的RawSocket初步些了个,但发现丢包现象严重,效果很不理想很多时候都嗅探不出来
后来借助httpwatch的API接口页很理想,大家有什么关于.net上的实现思虑么? vb.net或c#都行
下面这个基类是我仿照网上些的
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Net;
namespace v.sniffer
{
/**
* IP数据包结构,解释完毕的包存放到这里,最终用它来组成总的数据
*/
[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 class RawSocket
{
private bool error_occurred; //套接字在接收包时是否产生错误
public bool KeepRunning; //是否继续进行
private int len_receive_buf; //得到的数据流的长度
byte[] receive_buf_bytes; //收到的字节
private Socket socket = null; //声明套接字
const int SIO_RCVALL = unchecked((int)0x98000001);//监听所有的数据包
/**
* 构造函数
*/
public RawSocket()
{
error_occurred = false;//没有产生错误
len_receive_buf = 4096;//接收的数据流的长度
receive_buf_bytes = new byte[len_receive_buf];//接收的内容
}
/**
* 建立并绑定套接字
*
* @param 要监听的IP地址,单网卡的可以直接通过Dns.GetHostByName(Dns.GetHostEntry()).AddressList[0].ToString()方式来指定监听本地
*/
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;
}
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;//IP地址
PacketArrivedEventArgs e = new PacketArrivedEventArgs();//新网络数据包信息事件
fixed (byte* fixed_buf = buf)
{
IPHeader* head = (IPHeader*)fixed_buf;//把数据流整和为IPHeader结构
e.HeaderLength = (uint)(head->ip_verlen & 0x0F) << 2;
e.IPHeaderBuffer = new byte[e.HeaderLength];
temp_protocol = head->ip_protocol;
switch (temp_protocol)//提取协议类型
{
case 1: e.Protocol = "ICMP"; break;
ca
后来借助httpwatch的API接口页很理想,大家有什么关于.net上的实现思虑么? vb.net或c#都行
下面这个基类是我仿照网上些的
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Net;
namespace v.sniffer
{
/**
* IP数据包结构,解释完毕的包存放到这里,最终用它来组成总的数据
*/
[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 class RawSocket
{
private bool error_occurred; //套接字在接收包时是否产生错误
public bool KeepRunning; //是否继续进行
private int len_receive_buf; //得到的数据流的长度
byte[] receive_buf_bytes; //收到的字节
private Socket socket = null; //声明套接字
const int SIO_RCVALL = unchecked((int)0x98000001);//监听所有的数据包
/**
* 构造函数
*/
public RawSocket()
{
error_occurred = false;//没有产生错误
len_receive_buf = 4096;//接收的数据流的长度
receive_buf_bytes = new byte[len_receive_buf];//接收的内容
}
/**
* 建立并绑定套接字
*
* @param 要监听的IP地址,单网卡的可以直接通过Dns.GetHostByName(Dns.GetHostEntry()).AddressList[0].ToString()方式来指定监听本地
*/
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;
}
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;//IP地址
PacketArrivedEventArgs e = new PacketArrivedEventArgs();//新网络数据包信息事件
fixed (byte* fixed_buf = buf)
{
IPHeader* head = (IPHeader*)fixed_buf;//把数据流整和为IPHeader结构
e.HeaderLength = (uint)(head->ip_verlen & 0x0F) << 2;
e.IPHeaderBuffer = new byte[e.HeaderLength];
temp_protocol = head->ip_protocol;
switch (temp_protocol)//提取协议类型
{
case 1: e.Protocol = "ICMP"; break;
ca