前回はPcap.Netでキャプチャを実施しました。

Introduction

今回はSharpPcapを使います。ライセンスはLGPLです。

Nugetにパッケージはありますが、またも公式では無い様子。
githubに公式ページがありますが、Nugetについて言及が無いので、野良配布でしょう。
なので、githubのリリースページから最新版を入手します。
2017年3月末時点で4.2.0が最新版です。

Pcap.Netとは異なり、バイナリにx86版とx64版はありません。

  • SharpPcap.dll
  • PacketDotNet.dll

なので、前回と違って気にすることは少ないです。
また、SharpPcapはPacket.Netというライブラリに依存しています。こちらもLGPLです。
今回のソースは下記になります

Source

前回と同じ、Xamlです。
また、前回はinterfaceを駆使しているため、編集するソースは1ファイルだけになります。
実装をinterfaceで分離したかいがありました。
SharpPcapのライブラリは、sln ファイルと同じ階層にあるlibフォルダに、下記のように配置してください。

  • lib\SharpPcap-4.2.0\Release\SharpPcap.dll
  • lib\SharpPcap-4.2.0\Release\PacketDotNet.dll

PacketCaptureService

前回のソースを基準にしますので、interfaceは一切変更しません。
Pcap.NetのクラスをSharpPcapのクラスに置換したりするだけです。
修正ファイルは、PacketCaptureService.cs のみです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PacketDotNet;
using SharpPcap;
using WPF.PacketCapture.Models.Interfaces;
using WPF.PacketCapture.Services.Interfaces;

namespace WPF.PacketCapture.Services
{

public sealed class PacketCaptureService : IPacketCaptureService
{

#region Methods

public IEnumerable<IPacketCaptureDeviceModel> GetAllDevices()
{
return CaptureDeviceList.Instance.Select(device => new PacketCaptureDeviceModel(device));
}

#endregion

private sealed class PacketCaptureDeviceModel : IPacketCaptureDeviceModel
{

#region Events

public event EventHandler<IPacketModel> PacketReceived;

#endregion

#region Fields

private readonly ICaptureDevice _Device;

private Task _Task;

#endregion

#region Constructors

public PacketCaptureDeviceModel(ICaptureDevice device)
{
this._Device = device;
this._Device.OnPacketArrival += this.OnPacketReceived;
}

#endregion

#region Properties

public string Description => this._Device.Description;

public string Name => this._Device.Name;

#endregion

#region Methods

public void StartCapture()
{
this._Device.StopCapture();

// read timeout
var timeout = 1000;
this._Device.Open(DeviceMode.Promiscuous, timeout);
this._Device.Filter = "ip and tcp and port http";

this._Task?.Dispose();
this._Task = Task.Run(() =>
{
try
{
this._Device.StartCapture();
}
catch (Exception e)
{
Console.WriteLine(e);
}
});
}

public void StopCapture()
{
try
{
// 停止時に例外を投げるが原因が不明
this._Device.StopCapture();
}
catch (Exception e)
{
Console.WriteLine(e);
}

this._Task?.Dispose();
}

#region Helper Methods

private void OnPacketReceived(object sender, CaptureEventArgs captureEventArgs)
{
this.PacketReceived?.Invoke(this, new PacketModel(captureEventArgs.Packet));
}

#endregion

#endregion
}

private sealed class PacketModel : IPacketModel
{

#region Fields

private readonly Packet _Packet;

private readonly RawCapture _RawCapture;

#endregion

#region Constructors

public PacketModel(RawCapture rawPacket)
{
this._RawCapture = rawPacket;
this._Packet = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data);
}

#endregion

#region Properties

public string Destination => (this._Packet.PayloadPacket as IPv4Packet)?.DestinationAddress?.ToString();

public int Length => this._Packet.Bytes.Length;

public DateTime Timestamp => this._RawCapture.Timeval.Date;

public string Source => (this._Packet.PayloadPacket as IPv4Packet)?.SourceAddress?.ToString();

#endregion

}

}

}

Pcap.Netと異なり、DestnationやSourceを取得する際に、型のキャストが必要になるのが面倒かな。
パケットはデータリンク層かもしれないので、アドレスがない可能性があるのはわかりますが。
フィルタの構文はPcap.Netと同じです。
これは、WinPcapを使っているためです。

テスト

実際に実行してみます。
お好きなキャプチャデバイスを選択してStart Captureを押下することでキャプチャが実行されます。
HTTPのみ許容しているので、Webブラウザでどこかにアクセスしてみてください。
前回と全く同じです。

Conclusion

今回も簡単にキャプチャできました。
基本的にWinPcapのラッパーなので、似た使い方になるので、移植も簡単でしたね。

Source Code

https://github.com/takuya-takeuchi/Demo/tree/master/WPF/07_WPF.SharpPcap1