我创建了一个c ++程序,该程序通过fread函数读取和分析pcap文件。
这是一个程序,它通过指定每个协议标头结构来读取pcap文件的全局标头,读取pcap标头并提取特定的字段值。与tcpdump工具相比,tcpdump读取pcap文件的速度大约快三倍。我的程序真的很简单,但是我不知道为什么它很慢。我需要做些什么来提高程序的性能?
以下是我的代码。请注意,result(Variable)的类型为ostringstream。该程序通过重复调用analyze()读取所有pcap文件来工作。
PcapAnalyzer::PcapAnalyzer(const std::string& filename)
{
PcapAnalyzerfile = fopen("test.pcap", "r");
if (PcapAnalyzerfile == nullptr)
throw std::runtime_error("Failed to read Pcap");
struct PcapAnalyzer_file_header pfh;
if (fread(&pfh, sizeof(pfh), 1, PcapAnalyzerfile) < 1)
throw std::runtime_error("Failed to read Pcap");
if(pfh.linktype != 1)
throw std::runtime_error("No Support");
}
std::string PcapAnalyzer::analyze()
{
int process_len = 0;
int packet_len = 0;
result.str("");
result.clear();
packet_len = PcapAnalyzer_header();
if (packet_len == -1)
return {};
process_len = ethernet();
if (process_len == -1)
throw std::runtime_error("failed to analyze");
packet_len -= process_len;
if (!payload(packet_len))
throw std::runtime_error("failed to analyze");
return result.str();
}
int PcapAnalyzer::PcapAnalyzer_header()
{
struct PcapAnalyzer_pkthdr pp;
char* cap_time;
long sec;
if (fread(&pp, sizeof(pp), 1, PcapAnalyzerfile) < 1)
return -1;
sec = (long)pp.ts.tv_sec;
cap_time = (char*)ctime((const time_t*)&sec);
cap_time[strlen(cap_time) - 1] = '\0';
result << std::dec;
result << pp.len << " ";
result << cap_time << " ";
return pp.caplen;
}
int PcapAnalyzer::ethernet()
{
struct ether_header eh;
int process_len = 0;
if (fread(&eh, sizeof(eh), 1, PcapAnalyzerfile) < 1)
return -1;
process_len += sizeof(eh);
if(htons(eh.ether_type) != ETHERTYPE_IP)
return process_len;
process_len += ipv4();
if (process_len == -1)
throw std::runtime_error("failed to analyze");
return process_len;
}
int PcapAnalyzer::ipv4()
{
struct ip iph;
int opt = 0;
int process_len = 0;
if (fread(&iph, 20, 1, PcapAnalyzerfile) < 1)
return -1;
result << IP_V(iph.ip_vhl) << " ";
result << IP_HL(iph.ip_vhl) << " ";
result << iph.ip_tos << " ";
result << iph.ip_len << " ";
result << iph.ip_id << " ";
result << iph.ip_off << " ";
result << iph.ip_ttl << " ";
process_len += 20;
opt = IP_HL(iph.ip_vhl) * 4 - sizeof(iph);
if (opt != 0) {
fseek(PcapAnalyzerfile, opt, SEEK_CUR);
process_len += opt;
result << "ip_opt ";
}
if(iph.ip_p != IPPROTO_UDP)
return process_len;
process_len += udp();
if (process_len == -1)
throw std::runtime_error("failed to read transport header");
return process_len;
}
int PcapAnalyzer::udp()
{
struct udphdr udph;
int process_len = 0;
if (fread(&udph, sizeof(udph), 1, PcapAnalyzerfile) < 1)
return -1;
process_len += sizeof(udph);
result << ntohs(udph.uh_sport) << " ";
result << ntohs(udph.uh_dport) << " ";
result << ntohs(udph.uh_ulen) << " ";
result << ntohs(udph.uh_sum) << " ";
return process_len;
}
bool PcapAnalyzer::payload(int remain_len)
{
if (remain_len == 0)
return true;
char buffer[remain_len];
if (fread(buffer, remain_len, 1, PcapAnalyzerfile) < 1)
return false;
return true;
}