为什么我的 libpcap 会话中两个捕获的数据包之间有 0 秒的延迟?
Why is there a 0 second delay between two captured packets in my libpcap session?
我的分叉代理为每个传入连接复制:每个子进程启动一个分离的线程,该线程使用 pcap
会话记录该连接的数据包。查看我的日志文件,我发现属于同一连接的两个捕获数据包之间有 0 秒的延迟。
我不知道这是不是我的错误,或者我在 pcap
库中遗漏了什么,但这对我来说是一个严重的问题:延迟用于计算数据包每秒使用公式 1000000 / delay
(延迟以微秒为单位)。
这是我应该担心的事情吗?或者 pcap_pkthdr
没有提供足够的精度?我不熟悉接收数据包的速度有多快(我的笔记本电脑中的代理是 运行,我使用的是普通家庭网络,下载速度为 5 Mbps)。
这只发生在下载数据包时(当我正在获取 Debian ISO 或观看 YouTube 视频时),并且在将近 80000 个捕获的数据包中发生了 10 次。如果pcap_pkthdr
中的timeval
使用nanoseconds
,0延迟会消失吗?
无论如何,这是每个日志记录线程执行的代码:
int res;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *handle;
struct bpf_program fp;
bpf_u_int32 net = PCAP_NETMASK_UNKNOWN;
struct pcap_pkthdr *header;
const u_char *pkt_data;
struct timeval oldTimeUploadStruct;
struct timeval oldTimeDownloadStruct;
const char *filter_exp = // big filter of mine
handle = pcap_open_live("wlan0", 65535, 0, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device wlan0: %s\n", errbuf);
return;
}
// Compile and apply the filter
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
pcap_close(handle);
return;
}
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
pcap_close(handle);
return;
}
gettimeofday(&oldTimeUploadStruct, NULL);
gettimeofday(&oldTimeDownloadStruct, NULL);
long long oldTimeUpload = (oldTimeUploadStruct.tv_sec * 1000000) + oldTimeUploadStruct.tv_usec;
long long oldTimeDownload = (oldTimeDownloadStruct.tv_sec * 1000000) + oldTimeDownloadStruct.tv_usec;
// stopLogging is a flag set to false from child process before detaching this thread;
// when connection is over, the flag is set to true and this loop breaks
while ((res = pcap_next_ex(handle, &header, &pkt_data)) && (stopLogging == false)) {
// 0 if the timeout set with pcap_open_live() has elapsed.
// In this case pkt_header and pkt_data don't point to a valid packet
if (res == 0) {
continue;
}
if (packet is in upload) {
long long timestamp = (header->ts.tv_sec * 1000000) + header->ts.tv_usec;
long long delay = timestamp - oldTimeUpload;
std::stringstream mylogstream;
// creating string to log: I omitted some variables
// like IP addresses and ports for brevity
mylogstream << host << " UPLOAD " << timestamp << ' ' << header->caplen << ' ' << delay;
// logging captured packet
std::string mylog = mylogstream.str();
fs << mylog;
oldTimeUpload = timestamp;
}
else if (packet is in download) {
long long timestamp = (header->ts.tv_sec * 1000000) + header->ts.tv_usec;
long long delay = timestamp - oldTimeDownload;
std::stringstream mylogstream;
mylogstream << host << " DOWNLOAD " << timestamp << ' ' << header->caplen << ' ' << delay;
// logging captured packet
std::string mylog = mylogstream.str();
fs << mylog;
oldTimeDownload = timestamp;
}
}
if(res == -1)
printf("Error reading the packets: %s\n", pcap_geterr(handle));
debugGreen("Quit logging connection towards " << hostName);
pcap_close(handle);
因为您在同一个 CPU 时钟节拍内收到了两个数据包。由于网卡在接收数据包时会引发中断,因此这是可能的。
我的分叉代理为每个传入连接复制:每个子进程启动一个分离的线程,该线程使用 pcap
会话记录该连接的数据包。查看我的日志文件,我发现属于同一连接的两个捕获数据包之间有 0 秒的延迟。
我不知道这是不是我的错误,或者我在 pcap
库中遗漏了什么,但这对我来说是一个严重的问题:延迟用于计算数据包每秒使用公式 1000000 / delay
(延迟以微秒为单位)。
这是我应该担心的事情吗?或者 pcap_pkthdr
没有提供足够的精度?我不熟悉接收数据包的速度有多快(我的笔记本电脑中的代理是 运行,我使用的是普通家庭网络,下载速度为 5 Mbps)。
这只发生在下载数据包时(当我正在获取 Debian ISO 或观看 YouTube 视频时),并且在将近 80000 个捕获的数据包中发生了 10 次。如果pcap_pkthdr
中的timeval
使用nanoseconds
,0延迟会消失吗?
无论如何,这是每个日志记录线程执行的代码:
int res;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *handle;
struct bpf_program fp;
bpf_u_int32 net = PCAP_NETMASK_UNKNOWN;
struct pcap_pkthdr *header;
const u_char *pkt_data;
struct timeval oldTimeUploadStruct;
struct timeval oldTimeDownloadStruct;
const char *filter_exp = // big filter of mine
handle = pcap_open_live("wlan0", 65535, 0, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device wlan0: %s\n", errbuf);
return;
}
// Compile and apply the filter
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
pcap_close(handle);
return;
}
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
pcap_close(handle);
return;
}
gettimeofday(&oldTimeUploadStruct, NULL);
gettimeofday(&oldTimeDownloadStruct, NULL);
long long oldTimeUpload = (oldTimeUploadStruct.tv_sec * 1000000) + oldTimeUploadStruct.tv_usec;
long long oldTimeDownload = (oldTimeDownloadStruct.tv_sec * 1000000) + oldTimeDownloadStruct.tv_usec;
// stopLogging is a flag set to false from child process before detaching this thread;
// when connection is over, the flag is set to true and this loop breaks
while ((res = pcap_next_ex(handle, &header, &pkt_data)) && (stopLogging == false)) {
// 0 if the timeout set with pcap_open_live() has elapsed.
// In this case pkt_header and pkt_data don't point to a valid packet
if (res == 0) {
continue;
}
if (packet is in upload) {
long long timestamp = (header->ts.tv_sec * 1000000) + header->ts.tv_usec;
long long delay = timestamp - oldTimeUpload;
std::stringstream mylogstream;
// creating string to log: I omitted some variables
// like IP addresses and ports for brevity
mylogstream << host << " UPLOAD " << timestamp << ' ' << header->caplen << ' ' << delay;
// logging captured packet
std::string mylog = mylogstream.str();
fs << mylog;
oldTimeUpload = timestamp;
}
else if (packet is in download) {
long long timestamp = (header->ts.tv_sec * 1000000) + header->ts.tv_usec;
long long delay = timestamp - oldTimeDownload;
std::stringstream mylogstream;
mylogstream << host << " DOWNLOAD " << timestamp << ' ' << header->caplen << ' ' << delay;
// logging captured packet
std::string mylog = mylogstream.str();
fs << mylog;
oldTimeDownload = timestamp;
}
}
if(res == -1)
printf("Error reading the packets: %s\n", pcap_geterr(handle));
debugGreen("Quit logging connection towards " << hostName);
pcap_close(handle);
因为您在同一个 CPU 时钟节拍内收到了两个数据包。由于网卡在接收数据包时会引发中断,因此这是可能的。