単体テストにパケットキャプチャを組み込む α版
NUnitやVisual Studioのテストプロジェクトなどの単体テスト(Unit Test)で、ネットワークのやり取りをテスト条件に加えたかったので、
http://d.hatena.ne.jp/TripleX/20070527
http://msdn2.microsoft.com/ja-jp/library/bew39x2a(VS.80).aspx
このあたりを参考にして、パケットキャプチャを作ってみた。
まだ、きちんとテストしていないので使うときはat your own riskで。
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;namespace PacketUnit
{
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 8192;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
//public StringBuilder sb = new StringBuilder();public List
bytesReceived = new List (); public bool closed = false;
}public class CaptureCore
{
private string ipAddress;
public string IpAddress
{
get { return this.ipAddress; }
set { this.ipAddress = value; }
}private byte[] bytesCaputured;
public byte[] BytesCaputured
{
get { return this.bytesCaputured; }
}private StateObject state;
private Socket socket;public void StartCapture()
{
bytesCaputured = null;socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
socket.Bind(new IPEndPoint(IPAddress.Parse(this.IpAddress),0));byte[] byTrue = new byte[4] { 1, 0, 0, 0 };//この設定値の理由は不明
byte[] byOut = new byte[4];//この設定値の理由は不明socket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.HeaderIncluded,
true);socket.IOControl(IOControlCode.ReceiveAll,
byTrue,
byOut);state = new StateObject();
state.workSocket = socket;
socket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}public void EndCapture()
{
state.closed = true;
bytesCaputured = state.bytesReceived.ToArray();
}private static void ReceiveCallback(IAsyncResult ar)
{
StateObject currentstate = (StateObject)ar.AsyncState;
Socket currentsocket = currentstate.workSocket;int bytesRead = currentsocket.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
//state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
for(int i = 0; i < bytesRead; i++)
{
currentstate.bytesReceived.Add(currentstate.buffer[i]);
}// Get the rest of the data.
if (!currentstate.closed)
{
currentsocket.BeginReceive(currentstate.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), currentstate);
}
}
}
}
}
使い方
capture.StartCapture();
//
SomeNetworkOperations();
//
capture.EndCapture();
string captured = ToHexString(capture.BytesCaputured);
string expected = ToHexString(Encoding.ASCII.GetBytes("text to test"));
Assert.IsTrue(captured.IndexOf(expected) > -1);
private string ToHexString(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in bytes)
{
sb.Append(Convert.ToString(b, 16));
}
return sb.ToString();
}