如何提高文件读取性能?

时间:2018-08-11 12:13:04

标签: c++ performance fread tcpdump packet-sniffers

我创建了一个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;
}

0 个答案:

没有答案