網絡抓包,協議分析,流量統計程序



// YQPackageCaptureDlg.cpp : 實現文件
//

#include "stdafx.h"
#include "YQPackageCapture.h"
#include "YQPackageCaptureDlg.h"
#include "afxdialogex.h"
#include <pcap.h>
#include <vector>
#include <afxwin.h>
using namespace std;
#pragma warning(disable:4996)
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

/*_____________________________________________結構體_________________________________________*/
/* 4字節的IP地址 */
typedef struct ip_address
{
	u_char byte1;
	u_char byte2;
	u_char byte3;
	u_char byte4;
} ip_address;

/* IPv4 首部 */   //Internet Protocol version 4
typedef struct ip_header
{
	u_char  ver_ihl;        // 版本 (4 bits) + 首部長度 (4 bits)
	u_char  tos;            // 服務類型(Type of service)
	u_short tlen;           // 總長(Total length)
	u_short identification; // 標識(Identification)
	u_short flags_fo;       // 標志位(Flags) (3 bits) + 段偏移量(Fragment offset) (13 bits)
	u_char  ttl;            // 存活時間(Time to live)
	u_char  proto;          // 協議(Protocol)
	u_short crc;            // 首部校驗和(Header checksum)
	ip_address  saddr;      // 源地址(Source address)
	ip_address  daddr;      // 目的地址(Destination address)
	u_int   op_pad;         // 選項與填充(Option + Padding)
} ip_header;

/* UDP 首部*/
/*UDP 是User Datagram Protocol的簡稱,
中文名是用戶數據報協議,
是OSI(Open System Interconnection,開放式系統互聯)參考模型中一種無連接的傳輸層協議*/
typedef struct udp_header
{
	u_short sport;          // 源端口(Source port)
	u_short dport;          // 目的端口(Destination port)
	u_short len;            // UDP數據包長度(Datagram length)
	u_short crc;            // 校驗和(Checksum)
} udp_header;

/*TCP頭部*/
typedef struct tcp_header
{
	short m_sSourPort;                // 源端口號16bit
	short m_sDestPort;      // 目的端口號16bit
	unsigned int m_uiSequNum;      // 序列號32bit
	unsigned int m_uiAcknowledgeNum;  // 確認號32bit
	short m_sHeaderLenAndFlag;     // 前4位:TCP頭長度;中6位:保留;后6位:標志位
	short m_sWindowSize;    // 窗口大小16bit
	short m_sCheckSum;       // 檢驗和16bit
	short m_surgentPointer;     // 緊急數據偏移量16bit
}tcp_header;

typedef struct ip_flow
{
	ip_address  ipaddr;      // 源地址(Source address)
	float flow;             //該源地址的流量
}ip_flow;

typedef struct package_info
{
	u_char *package;      // 源地址(Source address)
	short len;             //該源地址的流量
}package_info;

/*_____________________________________________全局變量_________________________________________*/

int no = 0;
LARGE_INTEGER m_nFreq;         //內部計時器的時鍾周期,用於計時
LARGE_INTEGER m_nBeginTime;    //開始捕獲時,計時器的值,用於計時
vector<package_info> package_vec;
vector<ip_flow>ip_flow_vec;
CListCtrl CYQPackageCaptureDlg::list_package;
CListCtrl CYQPackageCaptureDlg::list_flow;
pcap_t *adhandle; //網卡句柄
pcap_if_t *alldevs;
pcap_if_t *d;
int stopNow=0;  //是否現在要停止捕獲

/*______________________________ 回調函數原型 ______________________________________________*/
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);


// 用於應用程序“關於”菜單項的 CAboutDlg 對話框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 對話框數據
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 實現
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CYQPackageCaptureDlg 對話框



CYQPackageCaptureDlg::CYQPackageCaptureDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_YQPACKAGECAPTURE_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CYQPackageCaptureDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_COMBO_ADAPTER, com_adapter);
	DDX_Control(pDX, IDC_LIST_PACKAGES, list_package);
	DDX_Control(pDX, IDC_LIST_FLOW, list_flow);
}

BEGIN_MESSAGE_MAP(CYQPackageCaptureDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_START_CAP, &CYQPackageCaptureDlg::OnBnClickedButtonStartCap)
	ON_CBN_SELCHANGE(IDC_COMBO_ADAPTER, &CYQPackageCaptureDlg::OnCbnSelchangeComboAdapter)
	ON_EN_CHANGE(IDC_EDIT_DESCRIPTION, &CYQPackageCaptureDlg::OnEnChangeEditDescription)
	ON_BN_CLICKED(IDC_BUTTON_STOP_CAP, &CYQPackageCaptureDlg::OnBnClickedButtonStopCap)
	ON_EN_CHANGE(IDC_EDIT_ASCII, &CYQPackageCaptureDlg::OnEnChangeEditAscii)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_PACKAGES, &CYQPackageCaptureDlg::OnLvnItemchangedListPackages)
END_MESSAGE_MAP()


// CYQPackageCaptureDlg 消息處理程序

BOOL CYQPackageCaptureDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 將“關於...”菜單項添加到系統菜單中。

	// IDM_ABOUTBOX 必須在系統命令范圍內。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 設置此對話框的圖標。  當應用程序主窗口不是對話框時,框架將自動
	//  執行此操作
	SetIcon(m_hIcon, TRUE);			// 設置大圖標
	SetIcon(m_hIcon, FALSE);		// 設置小圖標

	// TODO: 在此添加額外的初始化代碼
	/***________________________顯示可選的網卡__________________________***/
	//pcap_if_t *alldevs;
	//pcap_if_t *d;
	int inum;
	int adapter_counter = 0;           //網卡數目
	//pcap_t *adhandle; //網卡句柄
	char errbuf[PCAP_ERRBUF_SIZE];
	u_int netmask;
	char packet_filter[] = "ip and tcp or udp";   //程序最終可以得到IPV4,udp和tcp的數據包,並把它們復制給應用程序
	struct bpf_program fcode;   //伯克利封包過濾器(Berkeley Packet Filter,縮寫 BPF)
								//printf("%d\n", sizeof(u_char));
								/* 獲得設備列表 */
	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
	{
		fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
		exit(1);
	}

	/* 顯示網卡 */
	 //為組合框控件的列表框添加列表項
	for (d = alldevs; d; d = d->next)
	{
		CString name(d->name);
		com_adapter.InsertString(adapter_counter++, name);
		//adapter_counter++;
	}
	

	if (adapter_counter == 0)
	{
		AfxMessageBox(L"\nNo interfaces found! Make sure WinPcap is installed.\n");
		return -1;
	}
	// 默認選擇第一項   
	com_adapter.SetCurSel(0);
	
	/* 跳轉到已選設備 */
	inum = com_adapter.GetCurSel();
	int i;
	for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++);
	//顯示網卡描述
	CString description_str(d->description);
	SetDlgItemText(IDC_EDIT_DESCRIPTION, description_str);
	///* 釋放設備列表 */
	//pcap_freealldevs(alldevs);


	/*____________顯示control list package 的基本信息_______________________*/
	CRect rect;
	list_package.GetClientRect(&rect);   //獲得客戶區
	list_package.SetExtendedStyle(list_package.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);         //設置風格,LVS_EX_FULLROWSELECT是有線條,后面那個是充滿
																										  //插入列:
	list_package.InsertColumn(0, _T("NO."), LVCFMT_CENTER, rect.Width() /14, 0);
	list_package.InsertColumn(1, _T("Time"), LVCFMT_CENTER, rect.Width() / 7, 1);
	list_package.InsertColumn(2, _T("Source"), LVCFMT_CENTER, rect.Width() / 7, 2);
	list_package.InsertColumn(3, _T("Destination"), LVCFMT_CENTER, rect.Width() / 7, 3);
	list_package.InsertColumn(4, _T("Protocol"), LVCFMT_CENTER, rect.Width() /14, 4);
	list_package.InsertColumn(5, _T("Length"), LVCFMT_CENTER, rect.Width() / 14, 5);
	list_package.InsertColumn(6, _T("Info"), LVCFMT_CENTER, 5*rect.Width() /14, 6);


	list_flow.GetClientRect(&rect);   //獲得客戶區
	list_flow.SetExtendedStyle(list_package.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);         //設置風格,LVS_EX_FULLROWSELECT是有線條,后面那個是充滿
																													  //插入列:
	list_flow.InsertColumn(0, _T("源IP地址"), LVCFMT_CENTER, rect.Width() / 2, 0);
	list_flow.InsertColumn(1, _T("流量"), LVCFMT_CENTER, rect.Width() / 2, 1);
	
	return TRUE;  // 除非將焦點設置到控件,否則返回 TRUE
}

void CYQPackageCaptureDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向對話框添加最小化按鈕,則需要下面的代碼
//  來繪制該圖標。  對於使用文檔/視圖模型的 MFC 應用程序,
//  這將由框架自動完成。

void CYQPackageCaptureDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用於繪制的設備上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使圖標在工作區矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 繪制圖標
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//當用戶拖動最小化窗口時系統調用此函數取得光標
//顯示。
HCURSOR CYQPackageCaptureDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


/*開始捕獲按鈕*/
void CYQPackageCaptureDlg::OnBnClickedButtonStartCap()
{
	// TODO: 在此添加控件通知處理程序代碼
	//pcap_if_t *alldevs;
	//pcap_if_t *d;
	int inum;
	int adapter_counter = 0;
	
	char errbuf[PCAP_ERRBUF_SIZE];
	u_int netmask;
	char packet_filter[] = "ip and tcp or udp";   //程序最終可以得到IPV4,udp和tcp的數據包,並把它們復制給應用程序
	struct bpf_program fcode;   //伯克利封包過濾器(Berkeley Packet Filter,縮寫 BPF)
								//printf("%d\n", sizeof(u_char));
	
	/* 跳轉到已選設備 */
	inum= com_adapter.GetCurSel();
	int i;
	for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++);

	/* 打開適配器 */
	if ((adhandle = pcap_open(d->name,  // 設備名
		65536,     // 要捕捉的數據包的部分
				   // 65535保證能捕獲到不同數據鏈路層上的每個數據包的全部內容
		PCAP_OPENFLAG_PROMISCUOUS,         // 混雜模式
		1000,      // 讀取超時時間
		NULL,      // 遠程機器驗證
		errbuf     // 錯誤緩沖池
		)) == NULL)
	{
		AfxMessageBox(L"\nUnable to open the adapter. %s is not supported by WinPcap\n");
		fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
		/* 釋放設備列表 */
		pcap_freealldevs(alldevs);
		return ;
	}

	/* 檢查數據鏈路層,為了簡單,我們只考慮以太網 */
	/*返回鏈路層的類型,鏈路層的類型包括:
	DLT_NULL: BSD回路封裝;鏈路層協議頭是一個4字節的域,……
	DLT_EN10MB: 以太網(10Mb, 100Mb, 1000Mb, 或者更高)。
	DLT_IEEE802: IEEE802.5令牌環網。
	……
	*/
	if (pcap_datalink(adhandle) != DLT_EN10MB) //如果不是以太網就不處理了
	{
		AfxMessageBox(L"\nThis program works only on Ethernet networks.\n");
		fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
		/* 釋放設備列表 */
		pcap_freealldevs(alldevs);
		return ;
	}

	/*類型        格式          默認子網掩碼
	     A   網絡 節點 節點 節點  255.0.0.0
		      B   網絡 網絡 節點 節點  255.255.0.0
			       C   網絡 網絡 網絡 節點  255.255.255.0*/
	if (d->addresses != NULL)
		/* 獲得接口第一個地址的掩碼 */
		netmask = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
	else
		/* 如果接口沒有地址,那么我們假設一個C類的掩碼 */
		netmask = 0xffffff;


	//編譯過濾器pcap_compile
	if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0)
	{
		AfxMessageBox(L"\nUnable to compile the packet filter. Check the syntax.\n");
		fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
		/* 釋放設備列表 */
		pcap_freealldevs(alldevs);
		getchar();
		return ;
	}

	//設置過濾器pcap_setfilter
	if (pcap_setfilter(adhandle, &fcode)<0)
	{
		AfxMessageBox(L"\nError setting the filter.\n");
		fprintf(stderr, "\nError setting the filter.\n");
		/* 釋放設備列表 */
		pcap_freealldevs(alldevs);
		getchar();
		return ;
	}

	printf("\nlistening on %s...\n", d->description);

	/* 釋放設備列表 */
	pcap_freealldevs(alldevs);

	/* 開始捕捉並計時 */
	QueryPerformanceFrequency(&m_nFreq); // 獲取時鍾周期
	QueryPerformanceCounter(&m_nBeginTime);//獲取開始捕獲時,計時器的值

	pcap_loop(adhandle, 0, packet_handler, NULL);
	
}


void CYQPackageCaptureDlg::OnCbnSelchangeComboAdapter()
{
	// TODO: 在此添加控件通知處理程序代碼
	/* 跳轉到已選設備 */
	int inum = com_adapter.GetCurSel();
	int i;
	for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++);
	//顯示網卡描述
	CString description_str(d->description);
	SetDlgItemText(IDC_EDIT_DESCRIPTION, description_str);
	//SetDlgItemText(IDC_EDIT_DESCRIPTION, L"change my friend!!");

}

/****************************回調函數***********************************/
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
	//NO.   Time   Source   Destination     Protocol     Length     Info   十六進制   ASCII碼   流量統計
	//AfxMessageBox(L"抓到包了!");
	struct tm ltime;
	char timestr[16];
	ip_header *ih;
	udp_header *uh;
	tcp_header *th;
	u_int ip_len;
	time_t local_tv_sec;
	struct timeval tv_capPackage;
	

	/* 獲得IP數據包頭部的位置 */
	/*因為我們需要解析IP數據包,
	從IP數據包的首部解析到源IP地址和目的IP地址,
	而IP數據包的首部位於MAC首部的后面,所以我們需要跳過MAC首部。
	對於以太網而言MAC首部長度為14位*/

	ih = (ip_header *)(pkt_data +
		14); //以太網頭部長度 固定14位
	ip_len = (ih->ver_ihl & 0xf) * 4;   //ip首部有多少字節(取低四位,得到首部有多少個雙字;乘4得到字節數)

	/***************           顯示每個包的PCI   ****************************************/
	CString noStr;
	noStr.Format(_T("%d"), no+1);

	////插入該包數據,第0列(no)內容為1
	CYQPackageCaptureDlg::list_package.InsertItem(no, noStr);


	//Time
	LARGE_INTEGER m_nTime;
	QueryPerformanceCounter(&m_nTime);//獲取當前時間
	long long sec, next, time;   //從開始捕獲,到捕獲到當前包,時間差的秒,及其剩下的0.1秒;整個以微妙表示
	time = (m_nTime.QuadPart - m_nBeginTime.QuadPart) * 1000000 / m_nFreq.QuadPart;
	sec = time / 1000000;
	next = time - time / 1000000 * 1000000;
	//printf("Time:%lld.%.6lld \n", sec, next);
	CString timeStr;
	timeStr.Format(_T("%lld.%.6lld \n"), sec, next);
	//設置該包第1列(time)內容
	CYQPackageCaptureDlg::list_package.SetItemText(no , 1,timeStr);

	//Source

	CString sourceStr;
	sourceStr.Format(_T("%d.%d.%d.%d\n"),
		ih->saddr.byte1,
		ih->saddr.byte2,
		ih->saddr.byte3,
		ih->saddr.byte4);
	//設置該包第2列(source)內容
	CYQPackageCaptureDlg::list_package.SetItemText(no, 2,sourceStr);

	//Destination

	CString desStr;
	desStr.Format(_T("%d.%d.%d.%d\n"),
		ih->daddr.byte1,
		ih->daddr.byte2,
		ih->daddr.byte3,
		ih->daddr.byte4);
	//設置該包第3列(Destination)內容
	CYQPackageCaptureDlg::list_package.SetItemText(no, 3, desStr);

	//Protocol
	/*協議字段:占8比特。指明IP層所封裝的上層協議類型,
	如ICMP(1)、IGMP(2) 、TCP(6)、UDP(17)、EIGRP(88)、OSPF(89)等。*/
	CString protocolStr = NULL;
	CString Str;

	switch (ih->proto)
	{
	case 1:protocolStr = "ICMP";  break;
	case 2:protocolStr = "IGMP";  break;
	case 6:protocolStr = "TCP";  break;
	case 17:protocolStr = "UDP"; break;
	case 20:protocolStr = "HMP";  break;
	case 88:protocolStr = "EIGRP";  break;
	case 89:protocolStr = "OSPF";  break;
	default: protocolStr.Format(_T("%d", ih->proto));
	}
	CYQPackageCaptureDlg::list_package.SetItemText(no, 4,protocolStr);
	//printf("Protocol:%s\n", protocol);

	//Length
	CString lenStr;
	int wholeLen = ntohs(ih->tlen) + 14;  //將網絡字節序列轉換成主機字節序列,加上以太網包頭的長度
	lenStr.Format(_T("%d"), wholeLen);  
	CYQPackageCaptureDlg::list_package.SetItemText(no, 5, lenStr);

	//Info
	CString infoStr;
	//UDP
	//printf("Info:\n");
	if (protocolStr == "UDP")
	{
		/* 獲得UDP首部的位置 */

		uh = (udp_header *)((u_char*)ih + ip_len);
		infoStr.Format(_T("%d -> %d, Len=%d\n\n"), ntohs(uh->sport), ntohs(uh->dport), ntohs(uh->len));
	}
	else if (protocolStr == "TCP")
	{
		/* 獲得TCP首部的位置 */
		th = (tcp_header *)((u_char*)ih + ip_len);
		infoStr.Format(_T("%d -> %d, Seq=%u, Ack=%u, Win=%d "),
			ntohs(th->m_sSourPort),
			ntohs(th->m_sDestPort),
			ntohl(th->m_uiSequNum),
			ntohl(th->m_uiAcknowledgeNum),
			ntohs(th->m_sWindowSize)
			);
	}
	CYQPackageCaptureDlg::list_package.SetItemText(no, 6, infoStr);

	int list_item_count = CYQPackageCaptureDlg::list_package.GetItemCount();
	if (list_item_count   >   0)
		CYQPackageCaptureDlg::list_package.EnsureVisible(list_item_count - 1, FALSE);

	//十六進制
	CString hexStr,tempStr;
	u_char *temp = (u_char *)pkt_data;
	for (int i = 0; i < wholeLen; i++)
	{
		tempStr.Format(_T("%x "), *(temp++));
		hexStr += tempStr;
	}
	SetDlgItemText(AfxGetMainWnd()->m_hWnd,IDC_EDIT_HEX,hexStr);
	
	//ASCII碼
	CString asciiStr;
	temp = (u_char *)pkt_data;
	for (int i = 0; i < wholeLen; i++)
	{
		tempStr.Format(_T("%c "), *(temp++));
		asciiStr += tempStr;
	}
	SetDlgItemText(AfxGetMainWnd()->m_hWnd, IDC_EDIT_ASCII, asciiStr);

	//統計流量:
	int ip_count = size(ip_flow_vec);   //已經統計過的ip源地址
	int isNew = 1;    //之前沒出現過該ip源地址
	ip_flow new_ip_flow;
	CString flowStr;
	for (int i = 0; i < ip_count; i++)
	{
		//如果該ip地址已經出現過
		if (ih->saddr.byte1 == ip_flow_vec[i].ipaddr.byte1
			&&ih->saddr.byte2 == ip_flow_vec[i].ipaddr.byte2
			&&ih->saddr.byte3 == ip_flow_vec[i].ipaddr.byte3
			&&ih->saddr.byte4 == ip_flow_vec[i].ipaddr.byte4)
		{
			ip_flow_vec[i].flow += (double)wholeLen / 1024;  //單位為KB
			isNew = 0;

			flowStr.Format(_T("%.2f KB"), ip_flow_vec[i].flow);
			CYQPackageCaptureDlg::list_flow.SetItemText(i, 1, flowStr);
			break;
		}
	}
	//如果該ip地址此前沒有出現過
	if (isNew == 1)
	{
		new_ip_flow.ipaddr = ih->saddr;
		new_ip_flow.flow = (double)wholeLen / 1024;

		ip_flow_vec.push_back(new_ip_flow);
		flowStr.Format(_T("%.2f KB"),new_ip_flow.flow); 
		//插入該IP地址,顯示ip地址
		CYQPackageCaptureDlg::list_flow.InsertItem(ip_count, sourceStr);
		//顯示流量
		CYQPackageCaptureDlg::list_flow.SetItemText(ip_count, 1, flowStr);
	}
	list_item_count = CYQPackageCaptureDlg::list_flow.GetItemCount();
	if (list_item_count   >   0)
		CYQPackageCaptureDlg::list_flow.EnsureVisible(list_item_count - 1, FALSE);

	/*把包的內容存入package_vec*/
	temp = (u_char *)pkt_data;
	package_info new_package_info;
	new_package_info.package = temp;
	new_package_info.len = wholeLen;
	package_vec.push_back(new_package_info);

	//包的個數+1
	no++;
	//實時顯示
	UpdateWindow(AfxGetMainWnd()->m_hWnd);
	//CString mess;
	//mess.Format(_T("%d"), adhandle);
	//AfxMessageBox(mess);

	//判斷是否停止
	AfxGetApp()->PumpMessage();
	if (stopNow == 1)
	{
		pcap_breakloop(adhandle);  ///right here ahandle turned into 0
	}
}

void CYQPackageCaptureDlg::OnEnChangeEditDescription()
{
	// TODO:  如果該控件是 RICHEDIT 控件,它將不
	// 發送此通知,除非重寫 CDialogEx::OnInitDialog()
	// 函數並調用 CRichEditCtrl().SetEventMask(),
	// 同時將 ENM_CHANGE 標志“或”運算到掩碼中。

	// TODO:  在此添加控件通知處理程序代碼
}


void CYQPackageCaptureDlg::OnBnClickedButtonStopCap()
{
	// TODO: 在此添加控件通知處理程序代碼
	stopNow = 1;

}


void CYQPackageCaptureDlg::OnEnChangeEditAscii()
{
	// TODO:  如果該控件是 RICHEDIT 控件,它將不
	// 發送此通知,除非重寫 CDialogEx::OnInitDialog()
	// 函數並調用 CRichEditCtrl().SetEventMask(),
	// 同時將 ENM_CHANGE 標志“或”運算到掩碼中。

	// TODO:  在此添加控件通知處理程序代碼
}


void CYQPackageCaptureDlg::OnLvnItemchangedListPackages(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	// TODO: 在此添加控件通知處理程序代碼
	NMLISTVIEW *pnml = (NMLISTVIEW*)pNMHDR;//新建一個指針
	if (-1 != pnml->iItem)//如果指針無誤
	{
		CString pac_no_str;
		int pac_no;
		pac_no_str = list_package.GetItemText(pnml->iItem, 0);//如果鼠標選中了某行,將選中的行的第0列賦給str
		pac_no = _ttoi(pac_no_str)-1;
		

		CString hexStr, tempStr;
		u_char *temp = (u_char *)package_vec[pac_no].package;
		for (int i = 0; i < package_vec[pac_no].len; i++)
		{
			tempStr.Format(_T("%x "), *(temp++));
			hexStr += tempStr;
		}
		//CString len;
		//len.Format(_T("%d"), wholeLen);
		//AfxMessageBox(len);
		//SetDlgItemText(IDC_EDIT_HEX, L"exm");
		SetDlgItemText(IDC_EDIT_HEX, hexStr);

		//ASCII碼
		CString asciiStr;
		temp = (u_char *)package_vec[pac_no].package;
		for (int i = 0; i < package_vec[pac_no].len; i++)
		{
			tempStr.Format(_T("%c "), *(temp++));
			asciiStr += tempStr;
		}
		//SetDlgItemText(IDC_EDIT_ASCII, L"exm");
		SetDlgItemText(IDC_EDIT_ASCII, asciiStr);
		
	}


	*pResult = 0;
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM