我编写应用Wireshark文件(Pcap,Snopp,Pcapng ...)的应用程序打开此文件并读取所有数据包。
我的基类:
public abstract class WiresharkFile
{
...
}
我实施的所有子类IEnumerable
:
public class Libpcap:WiresharkFile,IDisposable,IEnumerable { .... }
现在,在创建对象时,我的代码会自动识别它,然后创建当前的object
类型,例如:
wiresharkFile = new Libpcap(file);
然后当我想循环我的文件并读取数据包时:
foreach (var packet in wiresharkFile)
{
}
所以得到这个错误:
foreach语句不能对WiresharkFile类型的变量进行操作' 因为WiresharkFile'不包含公共定义 '的GetEnumerator'
所以我在WiresharkFile基类中添加了这个函数:
public IEnumerator<WiresharkFilePacket> GetEnumerator()
{
return GetEnumerator();
}
现在转到此错误StackOverflowException:
无法计算表达式,因为当前线程位于堆栈中 溢出状态。
修改
public class Libpcap:WiresharkFile,IDisposable,IEnumerable { private BinaryReader binaryReader; 私人版本; 私人uint snaplen; private int thiszone; 私人uint sigfigs; private LibpcapLinkType linktype; 私人长基地; private bool byteSwap; private static uint MAGIC = 0xa1b2c3d4; private static uint MAGIC_ENDIAN = 0xd4c3b2a1;
public Libpcap(string path)
: this(new FileStream(path, FileMode.Open, FileAccess.Read))
{
FileName = path;
binaryReader = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read));
}
public void Close()
{
binaryReader.Close();
}
public enum LibpcapLinkType
{
Null,
Ethernet,
ExpEthernet,
AX25,
ProNet,
Chaos,
TokenRing,
ArcNet,
Slip,
Ppp,
Fddi
}
public Libpcap(Stream s)
{
binaryReader = new BinaryReader(s);
uint magic = binaryReader.ReadUInt32();
ushort major = binaryReader.ReadUInt16();
ushort minor = binaryReader.ReadUInt16();
thiszone = binaryReader.ReadInt32();
sigfigs = binaryReader.ReadUInt32();
snaplen = binaryReader.ReadUInt32();
uint ltype = binaryReader.ReadUInt32();
if (byteSwap)
{
major = ByteSwap.Swap(major);
minor = ByteSwap.Swap(minor);
thiszone = ByteSwap.Swap(thiszone);
snaplen = ByteSwap.Swap(snaplen);
ltype = ByteSwap.Swap(ltype);
}
version = new Version(major, minor);
linktype = (LibpcapLinkType)((int)ltype);
basePos = binaryReader.BaseStream.Position;
}
protected override WiresharkFilePacket ReadPacket()
{
if (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length)
{
int secs = binaryReader.ReadInt32();
int usecs = binaryReader.ReadInt32();
uint caplen = binaryReader.ReadUInt32();
uint len = binaryReader.ReadUInt32();
if (byteSwap)
{
secs = ByteSwap.Swap(secs);
usecs = ByteSwap.Swap(usecs);
caplen = ByteSwap.Swap(caplen);
len = ByteSwap.Swap(len);
}
DateTime timeStamp = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds((Double)secs).AddMilliseconds((Double)usecs / 1000);
byte[] data = binaryReader.ReadBytes((int)caplen);
return new WiresharkFilePacket(timeStamp, data);
}
else
return null;
}
public Version Version
{
get
{
return version;
}
}
public uint MaximumCaptureLength
{
get
{
return snaplen;
}
}
public int TimezoneOffset
{
get
{
return thiszone;
}
}
public uint SignificantFigures
{
get
{
return sigfigs;
}
}
public LibpcapLinkType LinkType
{
get
{
return linktype;
}
}
public void Rewind()
{
binaryReader.BaseStream.Position = basePos;
}
public override string ToString()
{
string endianness;
if (BitConverter.IsLittleEndian)
{
if (byteSwap)
endianness = "Big";
else
endianness = "Little";
}
else
{
if (byteSwap)
endianness = "Little";
else
endianness = "Big";
}
return String.Format("{0}-endian {1} capture, pcap version {2}", endianness, linktype.ToString(), version.ToString());
}
public void Dispose()
{
binaryReader.Close();
}
public class PacketEnumerator : IEnumerator<WiresharkFilePacket>
{
private Libpcap file;
private WiresharkFilePacket currentPacket = null;
public PacketEnumerator(Libpcap file)
{
this.file = file;
}
#region IEnumerator<PcapPacket> Members
public WiresharkFilePacket Current
{
get { return currentPacket; }
}
#endregion
#region IDisposable Members
public void Dispose()
{
}
#endregion
#region IEnumerator Members
object System.Collections.IEnumerator.Current
{
get { return currentPacket; }
}
public bool MoveNext()
{
currentPacket = file.ReadPacket();
return currentPacket != null;
}
public void Reset()
{
file.Rewind();
}
#endregion
}
#region IEnumerable<PcapPacket> Members
public IEnumerator<WiresharkFilePacket> GetEnumerator()
{
return new PacketEnumerator(this);
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new PacketEnumerator(this);
}
#endregion
}
答案 0 :(得分:0)
您看到的是11-15 07:19:53.298 2027-2027/? E/SIZE: 0
11-15 07:19:56.746 2027-2027/? E/SIZE: 2
11-15 07:19:57.765 2027-2027/? E/SIZE: 4
,因为您自称为
StackOverflowException
您需要正确实现迭代器才能使其正常工作。例如:
public IEnumerator<WiresharkFilePacket> GetEnumerator()
{
return GetEnumerator();
}
你的public IEnumerator<WiresharkFilePacket> GetEnumerator()
{
for (int i = 0; i < 10; i++)
yield return new WiresharkFilePacket();
}
应该有一些可以迭代的内部集合。无论是从pcap解析并返回的数据包。简单地创建WiresharkFile
方法将不会做任何事情。或许,您想阅读How do I implement IEnumerable<T>
答案 1 :(得分:0)
如果所有派生类都提供了GetEnumerator()
方法,并且您对任何将来的派生类都没有任何问题,但是您的基类无法有意义地定义一个,那么当您将其标记为abstract
时。 / p>
public abstract IEnumerator<WiresharkFilePacket> GetEnumerator();
这样就足以在你的基类上实现IEnumerable
,你还不需要完整的定义。