WinPcap网络抓包分析程序--总结

应付大作业写的一个程序,先给出程序的运行界面

程序的核心内容是抓包然后分析数据,我做的最多的也是协议分析这块内容。上面首先给出的是当前网络的上传下载速度,这块内容我是参考Windows性能计数器来写的,就是PDH,直接获取相应的接口,

获取数据,这块内容直接放出代码

 1 #include <Pdh.h>
 2 #include <list>
 3 #pragma comment(lib, "Pdh.lib")
 4
 5 class NetWorkSpeed
 6 {
 7 public:
 8     NetWorkSpeed();
 9     ~NetWorkSpeed();
10 public:
11     double getRecSpeed()  {return m_RecSpeed; }
12     double getSendSpeed() {return m_SendSpeed;}
13
14     bool init();
15
16     void update();
17 private:
18     double m_RecSpeed;
19     double m_SendSpeed;
20     HQUERY m_hQuery;
21
22     std::list<double>   m_receiveBps;
23     std::list<double>   m_sendBps;
24     std::list<HCOUNTER> m_allhCounters;
25 };

网络速度头文件

  1 using namespace std;
  2
  3 NetWorkSpeed::NetWorkSpeed()
  4 {
  5
  6 }
  7
  8 NetWorkSpeed::~NetWorkSpeed()
  9 {
 10     m_allhCounters.clear();
 11     m_sendBps.clear();
 12     m_receiveBps.clear();
 13
 14     PdhCloseQuery(m_hQuery);
 15 }
 16
 17 bool NetWorkSpeed::init()
 18 {
 19     DWORD counters_len=0;                                //计数器的个数
 20     DWORD instances_len=0;                               //网卡的个数
 21     string counters_names;                               //保存计数器名称
 22     string instances_names;                              //保存网卡名称
 23     const char* networkInterface="Network Interface";    //网络接口部分
 24
 25     PdhEnumObjectItemsA(0,0,networkInterface,0,&counters_len,0,&instances_len,PERF_DETAIL_WIZARD,0);
 26     counters_names.assign(counters_len,0);               //初始化字符串
 27     instances_names.assign(instances_len,0);
 28     if (ERROR_SUCCESS!=PdhEnumObjectItemsA(0,            //使用本地电脑不使用log日志文件
 29         0,                                               //使用本地电脑
 30         networkInterface,                                //接口声明
 31         &counters_names[0],                              //保存字符串
 32         &counters_len,                                   //个数
 33         &instances_names[0],
 34         &instances_len,
 35         PERF_DETAIL_WIZARD,                              //四种  这里是获取所有的计数器
 36         0))                                              //必须设置成0
 37         return false;
 38
 39
 40
 41     const char* in_speed="Bytes Received/sec";
 42     const char* out_speed="Bytes Sent/sec";
 43
 44     PDH_STATUS resulte=PdhOpenQuery(0,0,&m_hQuery);  //打开计数器
 45     if (ERROR_SUCCESS!=resulte)
 46         return false;                                //打开失败
 47
 48     char* tpStr=&instances_names[0];
 49     for(;*tpStr!=0;tpStr+=(strlen(tpStr)+1))
 50     {
 51         string pdh_Receive_path=string("\\")+networkInterface+"("+tpStr+")"+"\\"+in_speed;  //计数器具体路径
 52         string pdh_Sent_path=string("\\")+networkInterface+"("+tpStr+")"+"\\"+out_speed;
 53
 54         HCOUNTER tpCounter;
 55         resulte=PdhAddCounterA(m_hQuery,pdh_Receive_path.c_str(),0,&tpCounter);             //增加计数器
 56         if (ERROR_SUCCESS!=resulte)
 57             return false;
 58         m_allhCounters.push_back(tpCounter);                                                 //加入
 59
 60         resulte=PdhAddCounterA(m_hQuery,pdh_Sent_path.c_str(),0,&tpCounter);
 61         if (ERROR_SUCCESS!=resulte)
 62             return false;
 63         m_allhCounters.push_back(tpCounter);
 64     }
 65     return true;
 66 }
 67
 68 void NetWorkSpeed::update()
 69 {
 70     PDH_FMT_COUNTERVALUE relustValue;
 71     DWORD dType;
 72
 73     PDH_STATUS resulte=PdhCollectQueryData(m_hQuery);  //收集数据
 74
 75     double in_bps=0;
 76     double out_bps=0;
 77     double in_avg_bps=0;
 78     double out_avg_bps=0;
 79
 80     //遍历每个计数器
 81     for(list<HCOUNTER>::iterator begin=m_allhCounters.begin();begin!=m_allhCounters.end();begin++)
 82     {
 83         resulte=PdhGetFormattedCounterValue(*begin,PDH_FMT_DOUBLE,&dType,&relustValue);
 84         if (ERROR_SUCCESS==resulte)
 85             in_bps+=relustValue.doubleValue;  //增加
 86         begin++;
 87         resulte=PdhGetFormattedCounterValue(*begin,PDH_FMT_DOUBLE,&dType,&relustValue);
 88         if (ERROR_SUCCESS==resulte)
 89             out_bps+=relustValue.doubleValue;
 90     }
 91
 92     m_receiveBps.push_back(in_bps);
 93     m_sendBps.push_back(out_bps);
 94
 95     if (m_receiveBps.size()>10)
 96         m_receiveBps.pop_front();
 97     if (m_sendBps.size()>10)
 98         m_sendBps.pop_front();
 99
100     //计算平均值
101     in_avg_bps=accumulate(m_receiveBps.begin(),m_receiveBps.end(),0.0)/m_receiveBps.size();
102     out_avg_bps=accumulate(m_sendBps.begin(),m_sendBps.end(),0.0)/m_sendBps.size();
103
104     //转成 千字节
105     m_RecSpeed=in_avg_bps/1024;
106     m_SendSpeed=out_avg_bps/1024;
107 }

网络速度源文件

然后就是Pcap程序里面要做的第一步,选择网卡,然后打开设备,开启网卡的混杂模式,使用pcap_loop函数进行抓包,当然这里需要开启一条新的线程,具体的可以直接参考WinPcap入门文档里面的例子,这里我

先说一下我遇到的问题。开始我是每来一个包就进行分析,然后发现这种情况下是会丢包的,而且流量突然变大的时候丢包非常严重,会影响后面流量统计的精度。后来的话是打算参考WireShark的源代码,但无奈水平

不够,代码太复杂,就没看了。不过,我大概有下面一些理解,WireShark对发来的包是先存到堆里面,然后再取出分析,分析的话是采用树形的结构,确定它的父协议,然后一层层向下分析,而且它的插件开发也是向

协议树中进行注册,分析的时候就会通过插件,协议种类很多,这一块内容我还在学习,实现提供一个便捷的接口供外部注册使用。具体的分析网上很多,就不多说了。我呢,也是建立链表,将包数据存到链表里面,然后在

外部开启定时器,每隔一段时间对抓到的包进行分析,这样就能避免丢包。但是,需要注意的是,内存是有限的,所以必须定时的清理链表,释放相关的内存,当然你也可以先将数据写到文件里面,这一块需要你自己决定了。

这一块的话我就不给出相关代码了,毕竟网上太多了。

然后就是协议分析,先给出一些资料的链接, http://download.csdn.net/detail/zhoupeng39/8888363

这块我是写了两遍,毕竟看不看资料对不同协议的理解程度还是不同的,代码写的很简陋,如下

  1 //头部基类
  2 class Head_Top
  3 {
  4 public:
  5     Packet_Type own_type;    //记录类型
  6     int         own_len;     //记录长度
  7
  8     Head_Top():next(NULL){}
  9
 10     Head_Top* next;                                //下一个
 11
 12     virtual void packet_analysis(u_char* data,Packet_Type& type,int remain_len)=0;  //分析
 13
 14     virtual CString packet_own_print()=0;          //打印
 15
 16     virtual void    insertIntoTree(HTREEITEM root)=0;                    //形成树列表
 17 };
 18
 19 //以太网V2帧
 20 class Head_EthernetII: public Head_Top
 21 {
 22 public:
 23     u_char sMac[6];   //源Mac地址
 24     u_char dMac[6];   //目的Mac地址
 25     u_char kind[2];   //上层网络协议类型
 26
 27     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
 28
 29     CString packet_own_print();
 30
 31     void  insertIntoTree(HTREEITEM root);
 32 };
 33
 34 //以太网802.3帧
 35 class Head_802_3 : public Head_Top
 36 {
 37 public:
 38     u_char sMac[6];  //mac地址
 39     u_char dMac[6];
 40     u_char kind[2];  //类型
 41
 42     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
 43
 44     CString packet_own_print();
 45
 46     void  insertIntoTree(HTREEITEM root);
 47 };
 48
 49 //使用网线连接
 50 class Head_PPPoE : public Head_Top
 51 {
 52 public:
 53     u_short version;    //版本
 54     u_short pppoe_type; //类型
 55     u_short code;       //代码
 56     u_short session_id; //会话ID 保持不变
 57     u_short len;        //长度
 58     CString nextDataType;  //保存净荷域数据类型   只是分析IP包  其他类型未分析
 59
 60     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
 61
 62     CString packet_own_print();
 63
 64     void  insertIntoTree(HTREEITEM root);
 65 };
 66
 67 //地址解析协议
 68 class Head_ARP : public Head_Top
 69 {
 70 public:
 71     u_short handWareType;  //硬件类型  1 表示以太网
 72     u_short protocal_type; //协议类型  IP地址
 73     u_short handWare_Len;  //硬件长度  Mac地址 6个字节
 74     u_short protocal_len;  //协议长度  Ip地址  4个字节
 75     u_short op_code;       //操作码    1 请求 2 应答
 76     u_char sMac[6];        //源Mac
 77     u_char dMac[6];        //目的Mac
 78     u_char sIp[4];         //源IP
 79     u_char dIp[4];         //目的IP
 80
 81     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
 82
 83     CString packet_own_print();
 84
 85     void  insertIntoTree(HTREEITEM root);
 86 };
 87
 88 //IP协议
 89 class Head_IPv4 : public Head_Top
 90 {
 91 public:
 92     u_short version;    //版本号
 93     u_short header_len; //报头长度 *4为头部的长度  头部长度可变
 94     u_short service_type; //业务类型
 95     u_short len;          //数据包长度
 96     u_short sign;         //标识符 IP包分组时候使用  同一个标识符进行重组
 97     u_char    df;         //标记是否能分段   1 表示不能分段(不能分段 进行分段 会丢包处理)
 98     u_char    mf;          //分段包的结束操作 0 表示分段包的最后一个包
 99     u_short offset;       //分段偏移
100     u_char  TTL;          //存活时间
101     u_short protocol;     //下层协议类型
102     u_char sIp[4];        //源地址
103     u_char dIp[4];        //目的地址
104
105     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
106
107     CString packet_own_print();
108
109     void  insertIntoTree(HTREEITEM root);
110 };
111
112 //IPV6协议
113 class Head_IPv6 : public Head_Top
114 {
115 public:
116     u_char  version;   //IP版本  为6
117     u_char  trafficClass;  //通信类别
118     u_char  flowLabel[3];  //流标记
119     u_short next_len;      //负载长度  包括扩展头和上层载荷
120     u_short protocol;      //上层协议
121     u_short hopLimit;      //跳数限制
122     u_char sIp[16];        //源MAC
123     u_char dIp[16];        //目的MAC
124     u_short ext_len;       //扩展长度
125     u_short sign;          //标记是否存在扩展头部
126
127     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
128
129     CString packet_own_print();
130
131     void  insertIntoTree(HTREEITEM root);
132 };
133
134 //ICMP控制协议
135 class Head_ICMP : public Head_Top
136 {
137 public:
138     u_short ic_type;  //类型
139     u_short code;     //代码
140
141     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
142
143     CString packet_own_print();
144
145     void  insertIntoTree(HTREEITEM root);
146 };
147
148 //UDP协议
149 class Head_UDP : public Head_Top
150 {
151 public:
152     u_short sPort;   //源端口
153     u_short dPort;   //目的端口
154     u_short len;     //总长度
155
156     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
157
158     CString packet_own_print();
159
160     void  insertIntoTree(HTREEITEM root);
161 };
162
163
164 class Head_IGMP : public Head_Top
165 {
166 public:
167     u_char version;  //版本
168     u_char ig_type;  //类型
169     u_char Multicast[4];   //D类 组地址
170
171     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
172
173     CString packet_own_print();
174
175     void  insertIntoTree(HTREEITEM root);
176 };
177
178 //TCP协议
179 class Head_TCP : public Head_Top
180 {
181 public:
182     u_short sPort;        //源端口
183     u_short dPort;        //目的端口
184     int     seq;          //序号
185     int     refirm_seq;   //确认序号
186     u_short header_len;   //首部长度 *4
187     u_char  URG;          //紧急指针有效
188     u_char  ACK;          //确认字段有效
189     u_char  PSH;          //推送数据
190     u_char  RST;          //连接复位
191     u_char  SYN;          //连接建立时序号同步
192     u_char  FIN;          //终止连接
193     u_short window_size;  //窗口大小
194     u_short imppoint;     //紧急指针  标志那些数据可以优先处理
195
196     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
197
198     CString packet_own_print();
199
200     void  insertIntoTree(HTREEITEM root);
201 };
202
203 //OSPF协议
204 class Head_OSPF : public Head_Top
205 {
206 public:
207     u_char version;    //版本
208     u_short ospf_type; //报文类型
209     u_short len;       //长度
210     u_char routerIp[4];//路由器标识
211     u_char areaIp[4];  //区域标识
212     u_short autype;    //验证类型
213     CString auData;    //验证信息
214
215     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
216
217     CString packet_own_print();
218
219     void  insertIntoTree(HTREEITEM root);
220 };
221
222 //域名解析协议
223 class Head_DNS : public Head_Top
224 {
225 public:
226     u_short sign;         //唯一标识
227     u_char  symbol[2];    //标志
228     u_char  QR;           //查询还是响应报文
229     u_short questionNum;  //问题数目
230     u_short answerNum;    //回答数目
231     u_short au_answer;    //权威回答数目
232     u_short ex_answer;    //附加回答数目
233
234     CString question;     //问题
235
236     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
237
238     CString packet_own_print();
239
240     void  insertIntoTree(HTREEITEM root);
241 };
242
243 //DHCP协议
244 class Head_DHCP : public Head_Top
245 {
246 public:
247     u_char   op;     //操作代码
248     u_char   Htype;  //硬件地址类型  1表示以太网地址
249     u_short  Hlen;   //硬件地址长度
250     u_short  Hops;   //跳数  经过一个路由器加一
251     int      Transaction_ID;  //事务ID  请求和回复时判断的依据  唯一
252     u_short  Secs;   //客户机启动时间
253     u_char   Ciaddr[4];  //客户端IP地址  如果继续使用之前的IP 放在这里
254     u_char   Yiaddr[4];  //服务器提供的IP地址
255     u_char   Siaddr[4];  //服务器IP地址
256     u_char   Giaddr[4];  //转发代理地址  跨网段获取IP时候使用
257     u_char   Chaddr[6];  //客户端硬件地址  Mac地址
258     CString  Sname;      //服务器名称
259     CString  File;       //引导文件名称
260     u_short  message_type;  //消息类型  0x35 只是识别一种消息类型
261     u_short  message_in;    //具体消息
262
263     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
264
265     CString packet_own_print();
266
267     void  insertIntoTree(HTREEITEM root);
268 };
269
270 //超文本协议
271 class Head_HTTP : public Head_Top
272 {
273 public:
274     CString  HttpData;   //打印信息
275
276     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
277
278     CString packet_own_print();
279
280     void  insertIntoTree(HTREEITEM root);
281 };
282
283 //FTP协议分析 主动模式和被动模式  控制端口  数据端口
284 class Head_FTP : public Head_Top
285 {
286 public:
287     CString  command;    //只是打印命令  不做解析
288
289     void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
290
291     CString packet_own_print();
292
293     void  insertIntoTree(HTREEITEM root);
294 };
295
296 //简单邮件协议SMTP
297 class Head_SMTP : public Head_Top
298 {
299 public:
300      CString command;
301
302      void packet_analysis(u_char* data,Packet_Type& type,int remain_len);
303
304      CString packet_own_print();
305
306      void  insertIntoTree(HTREEITEM root);
307 };
308
309 #endif

源文件我给出部分代码,毕竟大同小异,看看上面的资料就都会写了

  1 void Head_EthernetII::packet_analysis(u_char* data,Packet_Type& type,int remain_len)
  2 {
  3     memcpy(dMac,data,6);
  4     memcpy(sMac,data+6,6);
  5     memcpy(kind,data+12,2);
  6
  7     int tmpKind=kind[0]<<8|kind[1];
  8
  9     own_type=EthernetII;
 10     own_len=14;
 11     remain_len-=own_len;
 12
 13     switch (tmpKind)
 14     {
 15     case sign_ipv4:
 16         next=new Head_IPv4();
 17         next->packet_analysis(data+14,type,remain_len);
 18         break;
 19     case sign_arp:
 20         next=new Head_ARP();
 21         next->packet_analysis(data+14,type,remain_len);
 22         break;
 23     case sign_ipv6:
 24         next=new Head_IPv6();
 25         next->packet_analysis(data+14,type,remain_len);
 26         break;
 27     case sign_pppoe:
 28         next=new Head_PPPoE();
 29         next->packet_analysis(data+14,type,remain_len);
 30         break;
 31     default:
 32         next=NULL;
 33         type=EthernetII;
 34         break;
 35     }
 36 }
 37
 38 void Head_PPPoE::packet_analysis(u_char* data,Packet_Type& type,int remain_len)
 39 {
 40     version=(data[0]&0xf0)>>4;
 41     pppoe_type=data[0]&0x0f;
 42     code=data[1];
 43     session_id=data[2]<<8|data[3];
 44     len=data[4]<<8|data[5];
 45
 46     own_type=PPPoE;
 47     own_len=8;
 48     remain_len-=own_len;
 49
 50     int kind=data[6]<<8|data[7];
 51
 52     if (0x0021==kind)
 53     {
 54         nextDataType="IP数据包";
 55         next=new Head_IPv4();
 56         next->packet_analysis(data+8,type,remain_len);
 57     }
 58     else
 59     {
 60         switch (kind)
 61         {
 62         case 0xc021:
 63              nextDataType="链路控制数据LCP";
 64              break;
 65         case 0x8021:
 66              nextDataType="网络控制数据NCP";
 67              break;
 68         case 0xc023:
 69              nextDataType="安全性认证PAP";
 70              break;
 71         case 0xc025:
 72              nextDataType="LQR";
 73              break;
 74         case 0xc223:
 75              nextDataType="安全性认证CHAP";
 76              break;
 77         }
 78         next=NULL;
 79         type=PPPoE;
 80     }
 81 }
 82
 83 void Head_IPv4::packet_analysis(u_char* data,Packet_Type& type,int remain_len)
 84 {
 85     version=(data[0]&0xf0)>>4;
 86     header_len=data[0]&0x0f;
 87     service_type=data[1];
 88     len=data[2]<<8|data[3];
 89     sign=data[4]<<8|data[5];
 90     df=data[6]&0x40>>6;
 91     mf=data[6]&0x20>>5;
 92     offset=(data[6]&0x1f)|data[7];
 93     TTL=data[8];
 94     protocol=data[9]&0xff;
 95     memcpy(sIp,data+12,4);
 96     memcpy(dIp,data+16,4);
 97
 98     own_type=IPv4;
 99     own_len=header_len*4;
100     remain_len=len-own_len;
101
102     switch (protocol)
103     {
104     case TYPE_ICMP_IPV4:
105          next=new Head_ICMP();
106          next->packet_analysis(data+header_len*4,type,remain_len);
107          break;
108     case TYPE_IGMP:
109          next=new Head_IGMP();
110          next->packet_analysis(data+header_len*4,type,remain_len);
111          break;
112     case TYPE_TCP:
113          next=new Head_TCP();
114          next->packet_analysis(data+header_len*4,type,remain_len);
115          break;
116     case TYPE_UDP:
117          next=new Head_UDP();
118          next->packet_analysis(data+header_len*4,type,remain_len);
119          break;
120     default:
121          next=NULL;
122          type=IPv4;
123         break;
124     }
125 }

好了,有了协议分析的结果,后面的三个模块就很好写了,这里先给出流程图

关于进程流量这块,没有映射到具体的程序上面,做的很简陋,给出部分代码

bool CProcessDlg::GetAllProcessesInfo()
{
    /*得到所有进程的快照*/
    HANDLE hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if(INVALID_HANDLE_VALUE==hProcessSnap)
        return false;

    /*保存进程信息的结构体*/
    PROCESSENTRY32 ProEntry32;
    memset(&ProEntry32,0,sizeof(ProEntry32));
    ProEntry32.dwSize=sizeof(ProEntry32);

    /*得到第一个进程的信息*/
    if(!Process32First(hProcessSnap,&ProEntry32))
    {
        CloseHandle(hProcessSnap);
        return false;
    }

    /*显示所有的进程的相关信息*/
    do
    {
        /*显示进程名称*/
        if (ProEntry32.th32ProcessID!=0)             //不包括系统进程
        {
            CString name=CString(ProEntry32.szExeFile);
            int index;
            if (isContainString(name,index))
                m_allProcesses[index]._processPID.push_back(ProEntry32.th32ProcessID);
            else
            {
                ProcessInfo tpInfo;
                tpInfo._processName=name;
                tpInfo._processPID.push_back(ProEntry32.th32ProcessID);
                m_allProcesses.push_back(tpInfo);
            }
         }
    } while(Process32Next(hProcessSnap,&ProEntry32));

    CloseHandle(hProcessSnap);
    return true;
}

void CProcessDlg::GetAllPortByProcessId(DWORD dwProcessId,std::vector<int>& port)
{
    HMODULE hModule=LoadLibraryW(L"iphlpapi.dll");
    if (hModule==NULL)
        return;                 //加载失败 

    //Win7 Vista系统下使用 

    //tcp 部分
    PMIB_TCPEXTABLE_VISTA pTcpExTable = NULL;
    PFNInternalGetTcpTable2 pInternalGetTcpTable2 = (PFNInternalGetTcpTable2)GetProcAddress(hModule, "InternalGetTcpTable2");
    if (pInternalGetTcpTable2!=NULL)
    {
       if (pInternalGetTcpTable2(&pTcpExTable, GetProcessHeap(), 1))
       {
          if (pTcpExTable)
             HeapFree(GetProcessHeap(), 0, pTcpExTable);
           FreeLibrary(hModule);
           hModule = NULL;
           return;
       }
       for (UINT i=0;i<pTcpExTable->dwNumEntries;i++)
       {
            // 过滤掉数据,只获取我们要查询的进程的 TCP Port 信息
            if(dwProcessId==pTcpExTable->table[i].dwProcessId)
                 port.push_back(ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort));
        }
        if (pTcpExTable)
            HeapFree(GetProcessHeap(), 0, pTcpExTable);
     }

    //udp 部分
    PMIB_UDPEXTABLE pUdpExTable=NULL;
    PFNInternalGetUdpTableWithOwnerPid pInternalGetUdpTableWithOwnerPid;
    pInternalGetUdpTableWithOwnerPid=(PFNInternalGetUdpTableWithOwnerPid)GetProcAddress(hModule, "InternalGetUdpTableWithOwnerPid");
    if (pInternalGetUdpTableWithOwnerPid != NULL)
    {
        if (pInternalGetUdpTableWithOwnerPid(&pUdpExTable, GetProcessHeap(), 1))
        {
            if (pUdpExTable)
                HeapFree(GetProcessHeap(), 0, pUdpExTable);
            FreeLibrary(hModule);
            hModule = NULL;
             return;
        }

        for (UINT i=0;i<pUdpExTable->dwNumEntries;i++)
        {
            if(dwProcessId == pUdpExTable->table[i].dwProcessId)
                 port.push_back(ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort));
        }

        if (pUdpExTable)
            HeapFree(GetProcessHeap(), 0, pUdpExTable);
     }
    FreeLibrary(hModule);
    hModule = NULL;
}

void CProcessDlg::OnTimer(UINT_PTR nIDEvent)
{
    clearAllSpeed();
    int maxSize=PData->getPackerResSize();
    for(int i=m_currSize;i<maxSize;i++)
    {
        int sPort,dPort;
        PacketAnalysis* res=PData->getPacketResAtIndex(i);
        if (res->getPort(sPort,dPort))  //获取到端口
        {
            for(int i=0;i<m_allProcesses.size();i++)
            {
                for(int j=0;j<m_allProcesses[i]._processPort.size();j++)
                {
                    if (m_allProcesses[i]._processPort[j]==sPort)
                    {
                        m_allProcesses[i]._upSpeed+=res->getLength();
                        m_allProcesses[i]._upTotal+=res->getLength();
                        break;
                    }
                    if (m_allProcesses[i]._processPort[j]==dPort)
                    {
                        m_allProcesses[i]._downSpeed+=res->getLength();
                        m_allProcesses[i]._downTotal+=res->getLength();
                        break;
                    }
                }
            }
        }
    }
    m_currSize=maxSize;

    //设置文本
    CString strItem;
    for(int i=0;i<m_allProcesses.size();i++)
    {
        strItem.Format("%.2lf",m_allProcesses[i]._upSpeed/1024);
        m_process.SetItemText(i,2,strItem);
        strItem.Format("%.2lf",m_allProcesses[i]._downSpeed/1024);
        m_process.SetItemText(i,3,strItem);
        strItem.Format("%.2lf",m_allProcesses[i]._upTotal/1024);
        m_process.SetItemText(i,4,strItem);
        strItem.Format("%.2lf",m_allProcesses[i]._downTotal/1024);
        m_process.SetItemText(i,5,strItem);
    }

    CDialogEx::OnTimer(nIDEvent);
}

然后就是最后一块,使用SQLITE数据库,简单的桌面型数据库,保存每段时间的流量,当然这里主要是绘图控件的使用,从MsChart到TeeChart,最后放弃使用这些复杂的控件,直接使用High Speed Charting Control,简单实用,具体的大家可以

看 http://www.codeproject.com/Articles/14075/High-speed-Charting-Control,网上的博客啥的写的都很浅,直接看作者给的例子,当然直接看源码是最好的了。给出部分代码

void SumPicDlg::initDlg()
{
    //初始化数据类型
    m_dataType.InsertString(0,"网络速度");
    m_dataType.InsertString(1,"月流量");
    m_dataType.InsertString(2,"日流量");
    m_dataType.InsertString(3,"时流量");
    m_dataType.SetCurSel(0);

    initSpeedSelect();

    //网络速度统计图初始化
    m_chartCtrl.EnableRefresh(false);

    m_chartCtrl.SetEdgeType(EDGE_SUNKEN);   //凹陷边框
    m_chartCtrl.SetBorderColor(RGB(0,180,0)); //边框颜色
    m_chartCtrl.SetBackColor(RGB(0,50,0));   //设置背景颜色
    m_chartCtrl.GetLegend()->SetVisible(true);  //解释文本可见
    m_chartCtrl.GetTitle()->AddString(_T("网络速度"));  //标题内容
    CChartFont titleFont;
    titleFont.SetFont(_T("Arial Black"),140,true,false,true);
    m_chartCtrl.GetTitle()->SetFont(titleFont);      //设置字体
    m_chartCtrl.GetTitle()->SetColor(RGB(200,0,10));  //设置颜色

    //创建坐标轴
    CChartStandardAxis* pLeftAxis=m_chartCtrl.CreateStandardAxis(CChartCtrl::LeftAxis);
    pLeftAxis->GetLabel()->SetText(_T("速度(K/S)"));
    pLeftAxis->SetAutomatic(true);
    pLeftAxis->GetGrid()->SetColor(RGB(0,180,0));
    CChartStandardAxis* pBottomAxis=m_chartCtrl.CreateStandardAxis(CChartCtrl::BottomAxis);
    pBottomAxis->SetMinMax(0,30);
    pBottomAxis->SetDiscrete(true);
    pBottomAxis->SetTickIncrement(false,1.0);
    pBottomAxis->GetGrid()->SetColor(RGB(0,180,0));

    CChartCrossHairCursor* pCursor=m_chartCtrl.CreateCrossHairCursor();    //交叉线光标
    m_chartCtrl.ShowMouseCursor(false);                                    //隐藏光标 

    //初始化数据
    for(int i=0;i<30;i++)
    {
        m_chartX[i]=i;
        m_recvChartY[i]=0;
        m_sendChartY[i]=0;
    }

    m_chartCtrl.RemoveAllSeries();   //去除所有的序列
    //创建折线数据
    CChartBarSerie* pBarSerie=m_chartCtrl.CreateBarSerie();
    CChartLineSerie* pRecvSerie=m_chartCtrl.CreateLineSerie();
    CChartLineSerie* pSendSerie=m_chartCtrl.CreateLineSerie();
    pRecvSerie->AddPoints(m_chartX,m_recvChartY,30);
    pRecvSerie->SetColor(RGB(255,0,0));
    pRecvSerie->SetName("接收速度");
    pRecvSerie->EnableShadow(true);
    pRecvSerie->SetShadowColor(RGB(128,255,128));
    pRecvSerie->SetWidth(2);
    pSendSerie->AddPoints(m_chartX,m_sendChartY,30);
    pSendSerie->SetColor(RGB(255,255,0));
    pSendSerie->SetName("发送速度");
    pSendSerie->EnableShadow(true);
    pSendSerie->SetWidth(2);
    pBarSerie->SetColor(RGB(255,255,0));
    pBarSerie->SetGradient(RGB(255,10,10),gtVertical);
    pBarSerie->SetName("");

    m_chartCtrl.EnableRefresh(true);

    m_toInitChart=false;     //不需要再初始化 

    SetTimer(UPDATE_SPEED,1000,NULL);
}

void SumPicDlg::addDataFromSQL(int maxNum,bool isLine,bool isBar,CChartBarSerie* pBar,CChartLineSerie* pLine)
{
    CString sql;
    m_chartCtrl.GetBottomAxis()->SetMinMax(0,maxNum+1);
    double* yValue=new double[maxNum];
    double  maxValue=0;
    for(int i=0;i<maxNum;i++)
    {
        switch (m_dataSrcIndex)
        {
        case 1: sql.Format("select sum(FlowSum) from Flow where Year=%d and Month=%d",m_selectYear,i+1); break;
        case 2: sql.Format("select sum(FlowSum) from Flow where Year=%d and Month=%d and Day=%d",m_selectYear,m_selectMonth,i+1); break;
        case 3: sql.Format("select sum(FlowSum) from Flow where Year=%d and Month=%d and Day=%d and Hour=%d",m_selectYear,m_selectMonth,m_selectDay,i+1);break;
        }
        PData->m_sqlInterFace.selectData(sql);
        if ((yValue[i]=PData->m_sqlInterFace.getDataAtIndex(0))==-1)
            yValue[i]=0;
        if (yValue[i]>maxValue)
            maxValue=yValue[i];
    }
    m_chartCtrl.GetLeftAxis()->SetMinMax(0,maxValue+maxValue/4);
    ((CChartStandardAxis*)m_chartCtrl.GetLeftAxis())->SetTickIncrement(false,(int)(maxValue/6));
    for(int i=0;i<maxNum;i++)
    {
        if (isLine)
        {
            sql.Format("%.1lf",yValue[i]);
            pLine->AddPoint(i+1,yValue[i]);
            pLine->CreateBalloonLabel(i,TChartString(sql));
        }
        if (isBar)
            pBar->AddPoint(i+1,yValue[i]);
    }
    delete[] yValue;
}

void SumPicDlg::OnBnClickedButtonCheck()
{
    m_chartCtrl.EnableRefresh(false);

    //获得 序列
    CChartLineSerie* pLine1=(CChartLineSerie*)m_chartCtrl.GetSerie(1);
    CChartBarSerie* pBar=(CChartBarSerie*)m_chartCtrl.GetSerie(0);
    pLine1->ClearSerie();
    pBar->ClearSerie();
    //获取 图表类型
    bool  isLine=m_checkLine.GetCheck();
    bool  isBar=m_checkBar.GetCheck();

#pragma region 图表初始化部分
    if (m_toInitChart)       //需要初始化 图表
    {
        pLine1->SetName("流量");
        pBar->SetName("流量");
        CChartLineSerie* pLine2=(CChartLineSerie*)m_chartCtrl.GetSerie(2);
        pLine2->ClearSerie();
        pLine2->SetName("");

        CChartStandardAxis* pLeft=(CChartStandardAxis*)m_chartCtrl.GetLeftAxis();
        pLeft->GetLabel()->SetText(_T("流量(Kb)"));
        pLeft->SetAutomatic(false);
        pLeft->SetMinMax(0,100);
        pLeft->SetTickIncrement(false,1);
        switch (m_dataSrcIndex)
        {
        case 1:
             m_chartCtrl.GetTitle()->RemoveAll();
             m_chartCtrl.GetTitle()->AddString(_T("月流量"));
             break;
        case 2:
             m_chartCtrl.GetTitle()->RemoveAll();
             m_chartCtrl.GetTitle()->AddString(_T("日流量"));
             break;
        case 3:
             m_chartCtrl.GetTitle()->RemoveAll();
             m_chartCtrl.GetTitle()->AddString(_T("时流量"));
        }
        m_toInitChart=false;
    }
#pragma endregion

    if (((CButton*)GetDlgItem(IDC_RADIO_LASTDAY))->GetCheck())
    {
         //暂时没写
    }
    else
    {
        switch (m_dataSrcIndex)
        {
        case 1:addDataFromSQL(m_maxMonthNum,isLine,isBar,pBar,pLine1);  break;
        case 2:addDataFromSQL(m_maxDayNum,isLine,isBar,pBar,pLine1);  break;
        case 3:addDataFromSQL(m_maxHourNum,isLine,isBar,pBar,pLine1);  break;
        }
    }

    m_chartCtrl.EnableRefresh(true);
}

差不多了,程序的源码在后面我会放出,当然只是入门级别的资料,程序写的很简陋。

时间: 2024-08-07 08:31:06

WinPcap网络抓包分析程序--总结的相关文章

python编写网络抓包分析脚本

python编写网络抓包分析脚本 写网络抓包分析脚本,一个称手的sniffer工具是必不可少的,我习惯用Ethereal,简单,易用,基于winpcap的一个开源的软件 Ethereal自带许多协议的 decoder,但是它的架构并不灵活,如果你要加入一个自己定义的的解码器,得去修改Ethereal的代码,再重新编译,相当的烦琐 对于一般的明文协议,没有什么问题,但是对于加密协议,比如网络游戏,客户端程序一般会在刚连接上的时候,发送一个随机密钥,而后的报文都会用这个密钥进 行加密,诸如此类.要想

对几款网络抓包工具的评测

对几款网络抓包工具的评测 by 拉登哥哥 最近在写个CMD远控 写着写着 想在服务端上做点手脚 都知道杀软误报 特别是黑软大部分都报毒 但实际上是正常的 对此可能部分人并不装杀软 基本上靠自己分析软件是否安全 1 低级点的 用相关工具 检测不能真的完全保证程序无毒  也没啥技术含量 原因是 可能你正在检测时 后门没激活(比如 我设置晚上12点才向外连接等) 你在白天或其它时间检测我的工具 可能没发现任何异常 晚上你开工具做事的时候 后门也跟着激活了 哈哈 这方法 实际中还真有人这么看 以前某个木

Wireshark数据抓包分析——网络协议篇

Wireshark是目前最受欢迎的抓包工具.它可以运行在Windows.Linux及MAC OS X操作系统中,并提供了友好的图形界面.同时,Wireshark提供功能强大的数据抓包功能.使用它,可以以各种方式抓取用户所需要的网络数据包. 但是用户往往无法从数据包中直接获取所需要的数据.这是由于所有的信息在传输过程中,都会被按照各种网络协议进行封装.用户想要从海量的数据抓包中获取的有用的信息,必须了解各种常见的网络协议.为了方便用户对数据包的分析,本书详细介绍了常用的各种网络协议,如ARP.IP

通信导论-网络协议抓包分析

一. 网络 网络规划表 源IP地址 默认网关 目的IP地址 域名 备注 192.168.43.16 192.168.43.1 104.74.21.164 360.com 360浏览器网页地址 192.168.43.16 192.168.43.1 182.232.136.130 yy.com 直播YY平台网页地址 2.配置 步骤:控制面板—网络和Internet—网络和共享中心—连接—属性—Internet协议版本4(TCP/IPv4)—属性—手动输入IP地址和DNS服务器地址 3.连通性测试 I

网络协议抓包分析——IP互联网协议

前言 IP协议是位于OSI模型的第三层协议,其主要目的就是使得网络间可以相互通信.在这一层上运行的协议不止IP协议,但是使用最为广泛的就是互联网协议. 什么是IP数据报 TCP/IP协议定义了一个在因特网上传输的包,称为IP数据报(IP Datagram).IP数据报是一个与硬件无关的虚拟包,由首部和数据两部分组成.首部部分主要包含版本.长度和IP地址等信息.数据部分一般用来传达其他协议如TCP.UDP和ICMP等.整个IP数据报的的首部表示总长度的字段位数为16位,于是可以表示的数据报最大大小

网络抓包wireshark(转)

转自 网络抓包wireshark 抓包应该是每个技术人员掌握的基础知识,无论是技术支持运维人员或者是研发,多少都会遇到要抓包的情况,用过的抓包工具有fiddle.wireshark,作为一个不是经常要抓包的人员,学会用Wireshark就够了,毕竟它是功能最全面使用者最多的抓包工具. Wireshark(前称Ethereal)是一个网络封包分析软件.网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料.Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换

Wireshark和TcpDump抓包分析对比

常见的抓包分析工具有:微软的Network Monitor和Message Analyzer.Sniff.WSExplorer.SpyNet.iptools.WinNetCap.WinSock Expert.Wireshark和linux的tcpdump等工具 今天,做了实验测试就对比分析其中的两款,其他的大家可以百度谷歌测试一哈^_^ 1. Wireshark与tcpdump介绍 Wireshark是一个网络协议检测工具,支持Windows平台和Unix平台,我一般只在Windows平台下使用

Wireshark和TcpDump抓包分析心得

? 1. Wireshark与tcpdump介绍 ?Wireshark是一个网络协议检测工具,支持Windows平台和Unix平台,我一般只在Windows平台下使用Wireshark,如果是Linux的话,我直接用tcpdump了,因为我工作环境中的Linux一般只有字符界面,且一般而言Linux都自带的tcpdump,或者用tcpdump抓包以后用Wireshark打开分析. 在Windows平台下,Wireshark通过WinPcap进行抓包,封装的很好,使用起来很方便,可以很容易的制定抓

网络数据包分析 网卡Offload

http://blog.nsfocus.net/network-packets-analysis-nic-offload/ 对于网络安全来说,网络传输数据包的捕获和分析是个基础工作,绿盟科技研究员在日常工作中,经常会捕获到一些大小远大于MTU值的数据包,经过分析这些大包的特性,发现和网卡的offload特性有关,本文对网卡Offload技术做简要描述. 文章目录 网络分片技术 网卡offload机制 发送模式 接收模式 网卡offload模式的设置 Linux windows 网卡Offload