Alex_McAvoy

想要成为渔夫的猎手

Sniffer 数据包接收线程

【概述】

数据包接收线程,是在已有的GUI上利用多线程技术进行数据接收,同时对GUI进行更新。因此,数据包接收线程,除了利用多线程进行数据接收外,还要在接收后对GUI控件进行更新

为此,需要提前编写一个更新数据包与更新列表的函数

对于更新数据包函数来说,每调用一次该函数,就对 GUI 的统计数据的包计数进行更新

对于更新列表的函数来说,每调用一次该函数,就为新接收到的数据包在 GUI 中的列表控件里新建项

【更新数据包】

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
//更新数据包
int CSnifferDlg::Sniffer_updatePacket() {
CString str;
str.Format("%d", this->packetNum.num_arp);
this->m_editARP.SetWindowText(str);

str.Format("%d", this->packetNum.num_ip4);
this->m_editIPv4.SetWindowText(str);

str.Format("%d", this->packetNum.num_ip6);
this->m_editIPv6.SetWindowText(str);

str.Format("%d", this->packetNum.num_icmp4);
this->m_editICMPv4.SetWindowText(str);

str.Format("%d", this->packetNum.num_icmp6);
this->m_editICMPv6.SetWindowText(str);

str.Format("%d", this->packetNum.num_udp);
this->m_editUDP.SetWindowText(str);

str.Format("%d", this->packetNum.num_tcp);
this->m_editTCP.SetWindowText(str);

str.Format("%d", this->packetNum.num_http);
this->m_editHTTP.SetWindowText(str);

str.Format("%d", this->packetNum.num_other);
this->m_editOther.SetWindowText(str);

str.Format("%d", this->packetNum.num_sum);
this->m_editSum.SetWindowText(str);

return 1;
}

【更新列表】

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
//更新列表
int CSnifferDlg::Sniffer_updateList(struct pcap_pkthdr *data_header, struct data_packet *data, const u_char *pkt_data) {
/********************初始化准备*********************/

//建立数据包链表,保存本地化后的数据
u_char *data_packet_list;
data_packet_list = (u_char*)malloc(data_header->len);
memcpy(data_packet_list, pkt_data, data_header->len);
this->m_localDataList.AddTail(data);
this->m_netDataList.AddTail(data_packet_list);

//获取长度
data->len = data_header->len;

//获取时间
time_t local_tv_sec = data_header->ts.tv_sec;
struct tm *ltime = localtime(&local_tv_sec);
data->time[0] = ltime->tm_year + 1900;
data->time[1] = ltime->tm_mon + 1;
data->time[2] = ltime->tm_mday;
data->time[3] = ltime->tm_hour;
data->time[4] = ltime->tm_min;
data->time[5] = ltime->tm_sec;

/********************更新控件*********************/
//为新接收到的数据包在列表控件中新建项
CString buffer;
buffer.Format("%d", this->packetNum);
int nextItem = this->m_listCtrl.InsertItem(this->packetNum, buffer);

//时间戳
CString timestr;
timestr.Format("%d/%d/%d %d:%d:%d", data->time[0],
data->time[1], data->time[2], data->time[3], data->time[4], data->time[5]);
this->m_listCtrl.SetItemText(nextItem, 1, timestr);

//长度
buffer.Empty();
buffer.Format("%d", data->len);
this->m_listCtrl.SetItemText(nextItem, 2, buffer);

//源MAC
buffer.Empty();
buffer.Format("%02X-%02X-%02X-%02X-%02X-%02X", data->ethh->src[0], data->ethh->src[1],
data->ethh->src[2], data->ethh->src[3], data->ethh->src[4], data->ethh->src[5]);
this->m_listCtrl.SetItemText(nextItem, 3, buffer);

//目的MAC
buffer.Empty();
buffer.Format("%02X-%02X-%02X-%02X-%02X-%02X", data->ethh->dest[0], data->ethh->dest[1],
data->ethh->dest[2], data->ethh->dest[3], data->ethh->dest[4], data->ethh->dest[5]);
this->m_listCtrl.SetItemText(nextItem, 4, buffer);

//协议
this->m_listCtrl.SetItemText(nextItem, 5, CString(data->type));

//源IP
buffer.Empty();
if (data->ethh->type == PROTO_ARP) {
buffer.Format("%d.%d.%d.%d", data->arph->src_ip[0],
data->arph->src_ip[1], data->arph->src_ip[2], data->arph->src_ip[3]);
}
else if (data->ethh->type == PROTO_IP_V4) {
struct in_addr in;
in.S_un.S_addr = data->ip4h->src_addr;
buffer = CString(inet_ntoa(in));
}
else if (data->ethh->type == PROTO_IP_V6) {
for (int i = 0; i < 8; i++) {
if (i <= 6)
buffer.AppendFormat("%02x:", data->ip6h->src_addr[i]);
else
buffer.AppendFormat("%02x", data->ip6h->src_addr[i]);
}
}
this->m_listCtrl.SetItemText(nextItem, 6, buffer);

//目的IP
buffer.Empty();
if (data->ethh->type == PROTO_ARP) {
buffer.Format("%d.%d.%d.%d", data->arph->dest_ip[0],
data->arph->dest_ip[1], data->arph->dest_ip[2], data->arph->dest_ip[3]);
}
else if (data->ethh->type == PROTO_IP_V4) {
struct in_addr in;
in.S_un.S_addr = data->ip4h->dest_addr;
buffer = CString(inet_ntoa(in));
}
else if (data->ethh->type == PROTO_IP_V6) {
for (int i = 0; i < 8; i++) {
if (i <= 6)
buffer.AppendFormat("%02x:", data->ip6h->dest_addr[i]);
else
buffer.AppendFormat("%02x", data->ip6h->dest_addr[i]);
}
}
this->m_listCtrl.SetItemText(nextItem, 7, buffer);
this->packetNum++;//包计数
return 1;
}

【接收线程】

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
接收线程函数
DWORD WINAPI Sniffer_capThread(LPVOID lpParameter) {
CSnifferDlg *pthis = (CSnifferDlg*)lpParameter;
if (pthis->m_ThreadHandle == NULL) {
MessageBox(NULL, "线程句柄错误", "提示", MB_OK);
return -1;
}

int flag;
struct pcap_pkthdr *data_header;//数据包头
const u_char *pkt_data = NULL;//收到的字节流数据
while ((flag = pcap_next_ex(pthis->catchHandle, &data_header, &pkt_data)) >= 0) {
/********************预处理判断*********************/
if (flag == 0)//超时
continue;

struct data_packet *data = (struct data_packet*)malloc(sizeof(struct data_packet));
memset(data, 0, sizeof(struct data_packet));

if (data == NULL) {
MessageBox(NULL, "空间已满,无法接收新的数据包", "Error", MB_OK);
return -1;
}

//分析出错或所接收数据包不在处理范围内
if (analyse_data_frame(pkt_data, data, &(pthis->packetCount)) < 0)
continue;

//将数据包保存到打开的文件中
if (pthis->dumpFile != NULL)
pcap_dump((unsigned char*)pthis->dumpFile, data_header, pkt_data);

/********************更新控件*********************/
pthis->Sniffer_updatePacket();
pthis->Sniffer_updateList(data_header, data, pkt_data);
}
return 1;
}
感谢您对我的支持,让我继续努力分享有用的技术与知识点!