[创建时间:2015-09-10 22:37:04]

NetAnalyzer下载地址

不好意思啊,NetAnalyzer停更有点长了,今天继续填坑^&^

NetAnalyzer实现结构

在上一篇中介绍一点VC++开发环境的配置,与基本的运行方式。因为NetAnalyzer使用的C#作为开发语言,所以在此主要介绍一些在C#环境下的开发环境的配置,与一些基本开发情况,力求在完成本篇后后,读者可以制作一个简单的抓包程序。

在开始编程前先要介绍连个.Net类库SharpPcap.dll与PacketDotNet.dll。在2004年Tamir Gal为了完成他的毕业设计,其中有一些内容需要使用Winpcap来实现网络数据分析,但希望可以使用简单易用的C#开发语言。于是建立了SharpPcap项目,Tamir Gal为了节省时间,并没用将网络数据采集部分与分析部分分开,甚至有些代码混杂在UI代码中。而且在实现了很少的WinPcapAPI接口,并没用提供相关的开发文档。

因为这样,Tamir决定重新设计SharPcap,并推出了1.x一些列的版本,最终在2007年完成了SharpPcap1.6.2版本。

在2008年11月Chris Morgan接替了Tamir的工作,重新设计了SharpPcap的API,开始支持Linux 和MAC(在Linux 与MAC平台的相关技术请参见Mono开发平台)。之后将数据采集于协议分析分别封装在不同的程序集类库中即形成了SharpPcap于Packet.Net。

下载地址:http://sourceforge.net/projects/sharppcap/ 在GNU协议下的开源代码。

(1)     SharpPcap.dll

SharpPcap中封装了Winpcap提供的大部分API函数,在该类库中,我们可以获取主机网卡,及其信息。并定义了对网卡的各种操作方法,如打开网卡,开始抓包,停止抓包等,再抓包中提供了,同步方式与异步方式,方便进行不同的环境,对于更加详细的介绍,将会在下一章提到。

(2)     Packet.Net

在程序集中的名称为PacketDotNet,该类库负责对捕获的数据进行分析解析,目前提供可以分析的协议:

Ethernet、SLL (Linux Cooked-Mode Capture) 、ARP、IPv4 、IPv6 、TCP 、UDP 、ICMPv4、ICMPv6 、IGMPv2 、PPPoE 、PTP 、LLDP 、Wake-on-LAN(WOL)

在NetAnalyzer此基础上,在类库中增加了PPP、LCP、CiscoHDLC等协议。

为了可以分析应用层协议,在NetAnalyzer设计了ApplicationProtocol类库,目前提供HTTP、FTP、DNS、SMTP、POP3、SSDP协议的解析,本节中不会对应用层协议进行分析。

在以下的内容中,我们将分七个部分,来完成一个简单的抓包程序。同上面一样,所有的程序都在Visual Studio2013中完成,只是在这里我们首先要得到:

SharpPcap.dll版本4.0.0

PacketDotNet.dl版本0.11.0

可以通过上面的网址获取。

1 获取网络适配器(网卡)

首先新建工程,开发语言选择C#,类型选择Windows窗体应用程序,命名为MySniffer,图形界面如图1所示。

图1 建立MySniffer工程

点击确定,在解决方案资源管理器中右击引用添加引用, 此时打开添加应用对话框,选择浏览选项卡,并找到SharpPcap与PacketDotNet类库将其添加至工程中。如图2所示,

图2从引用中右击添加引用

在添加完成之后,项目应用中应该可以看到这两个类库的的引用文件。

首先我们来获取需要监听的网卡,在窗体中添加如下代码:

         private void loadDevice()// 获取网卡方法
{
try
{
foreach (var i in CaptureDeviceList.Instance)
{
comDeviceList.Items.Add(i.Description); //在combox中添加
}
if (comDeviceList.Items.Count > )
{
comDeviceList.SelectedIndex = ;//自动选中第一个
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}

我们通过调用SharpPcap.CaptureDeviceList.Instance 单例,获取一个包含所用网卡的列表CaptureDeviceList,然后把以此把网卡的描述信息添加到顶部工具栏comDeviceList 中

在代码中我们加一个全局变量device用来指示当前控制的网卡,

         ICaptureDevice device;// 定义设备

所以当我们每次去选择不同的网卡时调用下面的方法

         //选择网卡
private void comDeviceList_SelectedIndexChanged(object sender, EventArgs e)
{
device = CaptureDeviceList.Instance[comDeviceList.SelectedIndex];
}

完成运行如图

图3获取的网卡以及其信息

接下来我们直接来点精彩的,加入如下代码:

         List<RawCapture> packetList = new List<RawCapture>();//捕获的数据列表
List<RawCapture> bufferList;//缓存列表
Thread AnalyzerThread;//分析数据的线程
object threadLock = new object();//线程锁定
bool isStartAnalyzer;//用于表示是否启动分析线程的标志
DeviceMode devMode = DeviceMode.Promiscuous;//数据采集模式
int readTimeOut = ;
delegate void DataGridRowsShowHandler(RawCapture packet); /// <summary>
/// 启动网卡
/// </summary>
private void Start()
{
if (device == null || device.Started)
return;
bufferList = new List<RawCapture>();
Clear();//清理原有的数据
isStartAnalyzer = true;
StartAnalyzer();//启动分析线程
try
{
device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival);
//默认使用混杂模式,超时 1000
device.Open(devMode, readTimeOut);
device.Filter = comFilter.Text;
device.StartCapture(); UIConfig(true);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); UIConfig(false);
} }
/// <summary>
/// 启动分析
/// </summary>
private void StartAnalyzer()
{
AnalyzerThread = new Thread(new ThreadStart(analysrThreadMethod));
AnalyzerThread.IsBackground = true;
AnalyzerThread.Start(); }
/// <summary>
/// 停止
/// </summary>
private void Stop()
{
try
{
if (device != null && device.Started)
{
device.StopCapture();
device.Close();
} isStartAnalyzer = false;
if (AnalyzerThread !=null && AnalyzerThread.IsAlive)
{
AnalyzerThread.Abort();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
UIConfig(false);
} /// <summary>
/// Sharpcap 获取数据包之后的回调
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void device_OnPacketArrival(object sender, CaptureEventArgs e)
{
lock (threadLock)
{
bufferList.Add(e.Packet);
}
} /// <summary>
/// 数据分析线程 (使用缓存方式,可避免数据堵塞)
/// </summary> private void analysrThreadMethod()
{
while (isStartAnalyzer)
{
bool isShoudSleep = true;
lock (threadLock)
{
if (bufferList.Count != )
isShoudSleep = false;
}
if (isShoudSleep)//
{
Thread.Sleep();
}
else
{
List<RawCapture> tmpPacketList;
lock (threadLock) //获取数据
{
tmpPacketList = bufferList;
bufferList = new List<RawCapture>();//构建新列表
packetList.AddRange(tmpPacketList);
}
foreach (var i in tmpPacketList)
{
this.Invoke(new DataGridRowsShowHandler(ShowDataRows), i); }
}
}
} /// <summary>
/// 在datagridview中显示获取的网络数据
/// </summary>
/// <param name="packet"></param>
private void ShowDataRows(RawCapture packet)
{
try
{
dataGridPacket.Rows.Add(rowsBulider.Row(packet, ++packetIndex));//加载DataGridRows;
}
catch (Exception ex)
{ }
}

这里通过在抓包启动之前,预先启动一个分析线程,用于独立进行数据解析,接下来就是在DataGridView中添加数据了,这部分写的比较渣,请轻喷,毕竟是几年前的代码了,代码如下:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpPcap;
using PacketDotNet;
using System.Xml;
namespace MySniffer
{
class DataBuilder
{
//标记当前数据是否有效 #region 构建数据行
/// <summary>
/// DataGridRow
/// </summary>
/// <returns>返回字符串数据</returns>
public string[] Row(RawCapture rawPacket, uint packetID)
{
string[] rows = new string[]; rows[] = string.Format("{0:D7}", packetID);//编号
rows[] = "Unknown";
rows[] = rawPacket.Data.Length.ToString();//数据长度bytes
rows[] = "--";
rows[] = "--";
rows[] = "--"; Packet packet = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data); EthernetPacket ep = EthernetPacket.GetEncapsulated(packet);
if (ep != null)
{
rows[] = "Ethernet(v2)";
rows[] = Format.MacFormat(ep.SourceHwAddress.ToString());
rows[] = Format.MacFormat(ep.DestinationHwAddress.ToString());
rows[] = "[" + ep.Type.ToString() + "]"; #region IP
IpPacket ip = IpPacket.GetEncapsulated(packet);
if (ip != null)
{
if (ip.Version == IpVersion.IPv4)
{
rows[] = "IPv4";
}
else
{
rows[] = "IPv6";
}
rows[] = ip.SourceAddress.ToString();
rows[] = ip.DestinationAddress.ToString();
rows[] = "[下层协议:" + ip.NextHeader.ToString() + "] [版本:" + ip.Version.ToString() + "]"; TcpPacket tcp = TcpPacket.GetEncapsulated(packet);
if (tcp != null)
{
rows[] = "TCP";
rows[] += " [" + tcp.SourcePort.ToString() + "]";
rows[] += " [" + tcp.DestinationPort.ToString() + "]"; return rows;
}
UdpPacket udp = UdpPacket.GetEncapsulated(packet);
if (udp != null)
{
rows[] = "UDP";
rows[] += " [" + udp.SourcePort.ToString() + "]";
rows[] += " [" + udp.DestinationPort.ToString() + "]";
return rows;
} ICMPv4Packet icmpv4 = ICMPv4Packet.GetEncapsulated(packet);
if (icmpv4 != null)
{
rows[] = "ICMPv4";
rows[] = "[校验:" + icmpv4.Checksum.ToString() + "] [类型:" + icmpv4.TypeCode.ToString() + "] [序列号:" + icmpv4.Sequence.ToString() + "]";
return rows;
}
ICMPv6Packet icmpv6 = ICMPv6Packet.GetEncapsulated(packet);
if (icmpv6 != null)
{
rows[] = "ICMPv6";
rows[] = "[Code:" + icmpv6.Code.ToString() + "] [Type" + icmpv6.Type.ToString() + "]";
return rows;
}
IGMPv2Packet igmp = IGMPv2Packet.GetEncapsulated(packet);
if (igmp != null)
{
rows[] = "IGMP";
rows[] = "[只适用于IGMPv2] [组地址:" + igmp.GroupAddress.ToString() + "] [类型:" + igmp.Type.ToString() + "]";
return rows;
}
return rows;
}
#endregion ARPPacket arp = ARPPacket.GetEncapsulated(packet);
if (arp != null)
{
rows[] = "ARP";
rows[] = Format.MacFormat(arp.SenderHardwareAddress.ToString());
rows[] = Format.MacFormat(arp.TargetHardwareAddress.ToString());
rows[] = "[Arp操作方式:" + arp.Operation.ToString() + "] [发送者:" + arp.SenderProtocolAddress.ToString() + "] [目标:" + arp.TargetProtocolAddress.ToString() + "]";
return rows;
}
WakeOnLanPacket wp = WakeOnLanPacket.GetEncapsulated(packet);
if (wp != null)
{
rows[] = "Wake On Lan";
rows[] = Format.MacFormat(ep.SourceHwAddress.ToString());
rows[] = Format.MacFormat(wp.DestinationMAC.ToString());
rows[] = "[唤醒网络地址:" + wp.DestinationMAC.ToString() + "] [有效性:" + wp.IsValid().ToString() + "]";
return rows;
}
PPPoEPacket poe = PPPoEPacket.GetEncapsulated(packet);
if (poe != null)
{
rows[] = "PPPoE";
rows[] = poe.Type.ToString() + " " + poe.Version.ToString();
return rows; }
LLDPPacket llp = LLDPPacket.GetEncapsulated(packet);
if (llp != null)
{
rows[] = "LLDP";
rows[] = llp.ToString();
return rows;
}
return rows;
}
//链路层
PPPPacket ppp = PPPPacket.GetEncapsulated(packet);
if (ppp != null)
{
rows[] = "PPP";
rows[] = "--";
rows[] = "--";
rows[] = "协议类型:" + ppp.Protocol.ToString();
return rows; }
//PPPSerial
PppSerialPacket ppps = PppSerialPacket.GetEncapsulated(packet);
if (ppps != null)
{
rows[] = "PPP";
rows[] = "--";
rows[] = "0x" + ppps.Address.ToString("X2");
rows[] = "地址:" + ppps.Address.ToString("X2") + " 控制:" + ppps.Control.ToString() + " 协议类型:" + ppps.Protocol.ToString();
return rows;
}
//Cisco HDLC
CiscoHDLCPacket hdlc = CiscoHDLCPacket.GetEncapsulated(packet);
if (hdlc != null)
{
rows[] = "Cisco HDLC";
rows[] = "--";
rows[] = "0x" + hdlc.Address.ToString("X2");
rows[] = "地址:" + hdlc.Address.ToString("X2") + " 控制:" + hdlc.Control.ToString() + " 协议类型:" + hdlc.Protocol.ToString();
return rows;
}
#warning 需要测试
PacketDotNet.Ieee80211.MacFrame ieee = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data) as PacketDotNet.Ieee80211.MacFrame;
if (ieee != null)
{
rows[] = "IEEE802.11 MacFrame";
rows[] = "--";
rows[] = "--";
rows[] = "帧校验序列:" + ieee.FrameCheckSequence.ToString() + " 封装帧:" + ieee.FrameControl .ToString();
return rows;
}
PacketDotNet.Ieee80211.RadioPacket ieeePacket = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data) as PacketDotNet.Ieee80211.RadioPacket;
if (ieeePacket != null)
{
rows[] = "IEEE Radio";
rows[] = "Version=" + ieeePacket.Version.ToString();
}
LinuxSLLPacket linux = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data) as LinuxSLLPacket;
if (linux != null)
{
rows[] = "LinuxSLL";
rows[] = "Tyep=" + linux.Type.ToString() + " Protocol=" + linux.EthernetProtocolType.ToString();
}
return rows;
}
}
#endregion }

虽然写的比较渣,但是思路还是蛮清晰的,额~~有砖头~~~~~

先不管了,来一起看看结果吧

图4 采集到网络数据

终于有点激动了,那么我们接下来就是要实现详细的数据了,不过看了上面的方式代码的解析方式,你会不会有点想法呢。好吧,我这边只把TCP的解析方式放在这里了

  //Tcp
TreeNode TCPNode;
TreeNode TcpFlagNode;
TreeNode TcpChecksumNode;
TreeNode TcpOptionsNode;
private void TCP(TcpPacket tcp)
{
if (TCPNode == null)
{
TCPNode = CreatNode("TCP", );
}
TCPNode.Nodes.Clear();
//port
TCPNode.Nodes.Add("Source Port: " + tcp.SourcePort.ToString());
TCPNode.Nodes.Add("Destination Port: " + tcp.DestinationPort.ToString());
// Seq and Ack
TCPNode.Nodes.Add("Sequence Number: " + tcp.SequenceNumber.ToString() + " [0x" + tcp.SequenceNumber.ToString("X") + "]");
TCPNode.Nodes.Add("Acknowledgement Number: " + tcp.AcknowledgmentNumber.ToString() + " [0x" + tcp.AcknowledgmentNumber.ToString("X") + "]");
//Data Offset
TCPNode.Nodes.Add("Data Offset: " + (tcp.DataOffset * ).ToString() + " [0x" + tcp.DataOffset.ToString("X") + "]");
//Flags
#region Flags
if (TcpFlagNode == null)
{
TcpFlagNode = new TreeNode();
}
TcpFlagNode.Nodes.Clear();
TcpFlagNode.Text = "Flags: [" + Format.TcpFlagType(tcp) + "] [0x" + string.Format("{0:X2}", tcp.AllFlags) + "]";
TcpFlagNode.Nodes.Add("000. .... .... = Reserved");
TcpFlagNode.Nodes.Add("...0 .... .... = Nonce");
TcpFlagNode.Nodes.Add(".... " + Format.getStaus(tcp.CWR) + "... .... = CWR");
TcpFlagNode.Nodes.Add(".... ." + Format.getStaus(tcp.ECN) + ".. .... = ECN-Echo");
TcpFlagNode.Nodes.Add(".... .." + Format.getStaus(tcp.Urg) + ". .... = URG");
TcpFlagNode.Nodes.Add(".... ..." + Format.getStaus(tcp.Ack) + " .... = ACK");
TcpFlagNode.Nodes.Add(".... .... " + Format.getStaus(tcp.Psh) + "... = PSH");
TcpFlagNode.Nodes.Add(".... .... ." + Format.getStaus(tcp.Rst) + ".. = RST");
TcpFlagNode.Nodes.Add(".... .... .." + Format.getStaus(tcp.Syn) + ". = SYN");
TcpFlagNode.Nodes.Add(".... .... ..." + Format.getStaus(tcp.Fin) + " = FIN");
TCPNode.Nodes.Add(TcpFlagNode);
#endregion
//WinSize
TCPNode.Nodes.Add("Window Size: " + tcp.WindowSize.ToString());
//check Sum
if (TcpChecksumNode == null)
{
TcpChecksumNode = new TreeNode();
}
TcpChecksumNode.Nodes.Clear();
TcpChecksumNode.Text = "Checksum: 0x" + tcp.Checksum.ToString("X") + " [" + (tcp.ValidChecksum ? "Valid" : "Invalid") + "]";
if (!tcp.ValidChecksum)
{
TCPNode.BackColor = TcpChecksumNode.BackColor = System.Drawing.Color.Red;
TCPNode.ForeColor = TcpChecksumNode.ForeColor = System.Drawing.Color.White;
}
else
{
TCPNode.BackColor = TcpChecksumNode.BackColor = Tree.BackColor;
TCPNode.ForeColor = TcpChecksumNode.ForeColor = Tree.ForeColor;
} TcpChecksumNode.Nodes.Add("Correct: " + tcp.ValidTCPChecksum.ToString());
TCPNode.Nodes.Add(TcpChecksumNode);
//Urgent
TCPNode.Nodes.Add("Urgent Pointer: " + tcp.UrgentPointer.ToString() + " [0x" + tcp.UrgentPointer.ToString("X") + "]");
//Options
if (tcp.Options.Length > )
{
if (TcpOptionsNode == null)
{
TcpOptionsNode = new TreeNode();
}
TcpOptionsNode.Nodes.Clear();
TcpOptionsNode.Text = "Options: " + tcp.Options.Length.ToString() + " bytes";
// [0x" + BitConverter.ToString(tcp.Options).Replace("-", "").PadLeft(12, '0') + "]
if (tcp.OptionsCollection != null)
{
var tmpColl = tcp.OptionsCollection;
for (int i = ; i < tmpColl.Count; i++)
{
TcpOptionsNode.Nodes.Add(tmpColl[i].ToString());
}
}
TCPNode.Nodes.Add(TcpOptionsNode);
}
Tree.Nodes.Add(TCPNode); AppNode(tcp.PayloadData, tcp.SourcePort, tcp.DestinationPort);
}

好了接下来让我们看看最终的结果吧

图5 带有数据协议解析的成果图

接下来就是一个关于文件存取的功能,毕竟可以把数据保存下来也是一件很酷的事情,(好吧,我是真的想不出一个好的理由……)

         //打开文件
private void btnOpen_Click(object sender, EventArgs e)
{
OpenFileDialog od = new OpenFileDialog();
od.Filter = "pcap文件|*.pcap"; if (od.ShowDialog() == DialogResult.OK)
{
Clear(); ICaptureDevice offDev = new SharpPcap.LibPcap.CaptureFileReaderDevice(od.FileName);
RawCapture tempPacket;
offDev.Open();
while ((tempPacket = offDev.GetNextPacket()) != null)
{
packetList.Add(tempPacket);
ShowDataRows(tempPacket);
}
offDev.Close(); }
} //文件保存
private void btnSave_Click(object sender, EventArgs e)
{
SaveFileDialog sd = new SaveFileDialog();
sd.Filter = "Pcap文件|*.pcap";
if (sd.ShowDialog() == DialogResult.OK)
{
var offDev = new SharpPcap.LibPcap.CaptureFileWriterDevice(sd.FileName);
foreach (var i in packetList)
{
offDev.Write(i);
}
MessageBox.Show("文件保存成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}

因为这里我们是直接通过Sharppcap调用winpcap内置的数据包存取方式,这样的好处是,我们可以用Wrieshark等一些其他抓包工具打开这些文件,当然如果你愿意也可以用自己的方式存取,只要保证在内存中可以转为RawCapture的数据列表就可以了

 

到这里了,制作一个简单的协议分析基本是完成了,这里是代码下载地址:http://yun.baidu.com/s/1dDDELzF

最后是一些个别说明,我们在监听网卡的时候有个模式的选项

 DeviceMode devMode = DeviceMode.Promiscuous;//数据采集模式

这里有连个模式一个常规模式 DeviceMode.Normal 和一个混杂模式 DeviceMode.Promiscuous主要是用于判断在网卡的数据监听方式,混杂模式就是接收所有经过网卡的数据包,包括不是发给本机的包。默认情况下网卡只把发给本机的包(包括广播包)传递给上层程序,其它的包一律丢弃。简单的讲,混杂模式就是指网卡能接受所有通过它的数据流,不管是什么格式,什么地址的。事实上,计算机收到数据包后,由网络层进行判断,确定是递交上层(传输层),还是丢弃,还是递交下层(数据链路层、MAC子层)转发。(这段来自百度)

还有一个就是关于超时设定,我们直接在程序中定义为1000ms 也就是1秒,也就是说通过winpcap每个1s向程序推送一次监听到的数据,这个值一定要合理设置,如果设置过短,就可能以为频繁提交数据造成性能开销和引起丢包,而如果过长再回造成界面响应慢,总之自己看情况设定吧

好了今天就写到这里吧,不足之处还请指正,祝你阅读愉快

NetAnalyzer下载地址

NetAnalzyer交流群:39753670 (PS 只提供交流平台,群主基本不说话^_^)

[转载请保留作者信息  作者:冯天文  网址:http://www.cnblogs.com/twzy/p/4769797.html ]

NetAnalyzer笔记 之 四. C#版的抓包软件的更多相关文章

  1. C#版的抓包软件

    C#版的抓包软件   [创建时间:2015-09-10 22:37:04] NetAnalyzer下载地址 不好意思啊,NetAnalyzer停更有点长了,今天继续填坑^&^ NetAnaly ...

  2. 手机抓包软件Charles安装使用实例 (流媒体播放测试可去下载的时刻检测)

    手机抓包软件Charles安装使用实例   浏览:5258 发布日期:2015/07/17 分类:技术分享 关键字: 手机抓包软件 Charles 大胡子的博客Charles安装使用实例 Charle ...

  3. 如何在Windows系统上用抓包软件Wireshark截获iPhone等网络通讯数据

    http://www.jb51.net/os/windows/189090.html 今天给大家介绍一种如何在Windows操作系统上使用著名的抓包工具软件Wireshark来截获iPhone.iPa ...

  4. Mac用户抓包软件Charles 4.0 破解 以及 抓取Https链接设置

    相信大家曾经都是Window的用户,作为前端哪能没有一款抓包工具,抓包工具可以非常便捷的帮助我们分析接口返回报文数据,快速定位问题. 曾经横扫window用户的Fiddler便是我们的挚爱,然而,作为 ...

  5. CatchPacket网络抓包软件

    CatchPacket网络抓包软件  qq  22945088431.技术特点:基于WinPcap库,c# winform2.实现获取机器所有网卡,可任意选择监听3.可以捕获常见网络协议arp dns ...

  6. 抓包软件PowerSniff开发计划

    目前抓包的工具不顺手: (1)smartsniff, minisniffer不支持插件 (2)wireshark,omnipeek插件过于复杂,还有不是要装驱动就是admin权限 打算重写一个,第一个 ...

  7. 比Wireshark更轻量、更方便的抓包软件:Charles

    转:http://blog.csdn.net/lixing333/article/details/42776187 之前写过一篇通过Wireshark进行抓包,分析网络连接的文章<通过WireS ...

  8. 第三百三十节,web爬虫讲解2—urllib库爬虫—实战爬取搜狗微信公众号—抓包软件安装Fiddler4讲解

    第三百三十节,web爬虫讲解2—urllib库爬虫—实战爬取搜狗微信公众号—抓包软件安装Fiddler4讲解 封装模块 #!/usr/bin/env python # -*- coding: utf- ...

  9. 分享三个USB抓包软件---Bus Hound,USBlyzer 和-USBTrace(转)

    源:分享三个USB抓包软件---Bus Hound,USBlyzer 和-USBTrace Bus Hound官方下载地址:http://perisoft.net/bushound/Bus Hound ...

随机推荐

  1. 对C++默认构造函数的理解

    在文章开始之前,首先指出对于c++新手的两个常见的误解: 一.任何class如果没有定义default constructor,就会被合成出一个来. 二.编译器合成出来的default constru ...

  2. POJ 2752 Seek the Name, Seek the Fame(next数组的理解)

    做此题,只要理解好next数组就行....................... #include <cstdio> #include <cmath> #include < ...

  3. Java基础知识强化61:经典查找之 常见查找算法小结

    一.顺序查找 条件:无序或有序队列. 原理:按顺序比较每个元素,直到找到关键字为止. 时间复杂度:O(n) 二.二分查找(折半查找) 条件:有序数组 原理:查找过程从数组的中间元素开始,如果中间元素正 ...

  4. HTML1.0 - html 环境搭建 开发工具

    1. mac  电脑 2. Hbuilder 开发软件 3. 学习基础 HTML 语法 网站  http://www.w3school.com.cn

  5. 【转】使用 Eclipse 调试 Java 程序的 10 个技巧

    你应该看过一些如<关于调试的N件事>这类很流行的帖子 .假设我每天花费1小时在调试我的应用程序上的话,那累积起来的话也是很大量的时间.由于这个原因,用这些时间来重视并了解所有使我们调试更方 ...

  6. SqlServer死锁与阻塞检测脚本

    IF EXISTS (SELECT * FROM sysobjects WHERE [name] = 'sp_Lock_Scan') DROP PROCEDURE sp_Lock_Scan GO CR ...

  7. iOS 数据持久化

    一.plist文件存储 获得文件 NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDom ...

  8. Java系列--第六篇 基于Maven的SSME之多国语言实现

    如果你的网站足够强大,以致冲出了国门,走向了国际的话,你就需要考虑做多国语言了,不过,未雨绸缪,向来是我辈程序人员的优秀品质,谁知道那天,我们的网站被国外大公司看中收购,从而飞上枝头变凤凰.不扯这么多 ...

  9. Apache主站点配置

    Apache的配置由httpd.conf文件配置,因此下面的配置指令都是在httpd.conf文件中修改. Apache主站点基本配置:ServerRoot "/mnt/software/a ...

  10. for_each 用法!

    class MapTest:public CapTest{ private: set <string> MyTestContain; typedef pair <string,int ...