#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcap.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#define SAMPLE_COUNT 0 // 0表示无限采样
#define TARGET_MAX 32
#define INTERVAL 2 // 采样间隔(秒)
typedef struct {
const char *ip;
int port;
unsigned long long bytes_sent;
unsigned long long bytes_recv;
double send_mbps;
double recv_mbps;
} target_t;
target_t targets[TARGET_MAX];
int target_count = 0;
int link_offset = 14;
volatile int running = 1;
void signal_handler(int sig) {
running = 0;
}
void add_target(const char *ip, int port) {
if(target_count >= TARGET_MAX) {
fprintf(stderr, "Too many targets!\n");
exit(1);
}
targets[target_count].ip = ip;
targets[target_count].port = port;
targets[target_count].bytes_sent = 0;
targets[target_count].bytes_recv = 0;
targets[target_count].send_mbps = 0.0;
targets[target_count].recv_mbps = 0.0;
target_count++;
}
int get_link_offset(pcap_t *handle) {
int linktype = pcap_datalink(handle);
if(linktype == DLT_EN10MB) return 14;
else if(linktype == DLT_LINUX_SLL) return 16;
else {
fprintf(stderr, "Unsupported datalink type: %d\n", linktype);
exit(1);
}
}
void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) {
(void)user;
if (h->len < link_offset + 20) return;
struct ip *ip_hdr = (struct ip*)(bytes + link_offset);
if(ip_hdr->ip_v != 4) return;
int ip_hdr_len = ip_hdr->ip_hl * 4;
if (h->len < link_offset + ip_hdr_len + 20) return;
struct tcphdr *tcp_hdr = (struct tcphdr*)((u_char*)ip_hdr + ip_hdr_len);
char src_ip[16], dst_ip[16];
inet_ntop(AF_INET, &ip_hdr->ip_src, src_ip, sizeof(src_ip));
inet_ntop(AF_INET, &ip_hdr->ip_dst, dst_ip, sizeof(dst_ip));
// 使用标准的TCP头字段名
int src_port = ntohs(tcp_hdr->source);
int dst_port = ntohs(tcp_hdr->dest);
for(int i = 0; i < target_count; i++) {
// 本机发向目标
if(strcmp(dst_ip, targets[i].ip) == 0 && dst_port == targets[i].port) {
targets[i].bytes_sent += h->len;
}
// 目标发向本机
if(strcmp(src_ip, targets[i].ip) == 0 && src_port == targets[i].port) {
targets[i].bytes_recv += h->len;
}
}
}
void print_header() {
printf("\033[2J\033[H");
printf("================================================================================\n");
printf(" 实时带宽监控 (基于libpcap) - 端口: 9092\n");
printf("================================================================================\n");
printf("%-20s %-8s %-12s %-12s %-8s\n",
"IP地址", "端口", "发送(Mbps)", "接收(Mbps)", "总带宽(Mbps)");
printf("--------------------------------------------------------------------------------\n");
}
void print_stats() {
double total_send_mbps = 0.0;
double total_recv_mbps = 0.0;
int active_targets = 0;
for(int i = 0; i < target_count; i++) {
double total_mbps = targets[i].send_mbps + targets[i].recv_mbps;
printf("%-20s %-8d %-12.2f %-12.2f %-8.2f\n",
targets[i].ip,
targets[i].port,
targets[i].send_mbps,
targets[i].recv_mbps,
total_mbps);
total_send_mbps += targets[i].send_mbps;
total_recv_mbps += targets[i].recv_mbps;
if (targets[i].send_mbps > 0 || targets[i].recv_mbps > 0) {
active_targets++;
}
}
printf("--------------------------------------------------------------------------------\n");
printf("总计: %d个目标 | 总发送: %.2f Mbps | 总接收: %.2f Mbps | 总带宽: %.2f Mbps\n",
active_targets, total_send_mbps, total_recv_mbps, total_send_mbps + total_recv_mbps);
printf("================================================================================\n");
printf("按 Ctrl+C 停止监控\n");
}
int main() {
signal(SIGINT, signal_handler);
// 添加目标 IP:Port
add_target("10.252.12.100", 9092);
add_target("10.252.134.67", 9092);
add_target("10.252.134.68", 9092);
add_target("10.252.134.69", 9092);
add_target("10.252.134.70", 9092);
add_target("10.252.134.71", 9092);
add_target("10.52.16.68", 9092);
add_target("10.52.16.69", 9092);
add_target("10.52.16.70", 9092);
add_target("10.52.16.71", 9092);
add_target("10.52.16.72", 9092);
add_target("10.252.12.83", 9092);
add_target("10.252.12.84", 9092);
add_target("10.252.12.85", 9092);
add_target("10.252.12.86", 9092);
add_target("10.252.12.87", 9092);
add_target("10.252.12.88", 9092);
add_target("10.252.12.89", 9092);
add_target("10.252.145.44", 9092);
add_target("10.252.12.99", 9092);
char errbuf[PCAP_ERRBUF_SIZE];
// 直接使用 eth0
const char *iface = "eth0";
// 显示可用网卡
pcap_if_t *alldevs;
if (pcap_findalldevs(&alldevs, errbuf) == 0) {
printf("可用网卡:\n");
for(pcap_if_t *d = alldevs; d; d = d->next) {
printf(" %s", d->name);
if (d->description) printf(" (%s)", d->description);
printf("\n");
}
pcap_freealldevs(alldevs);
}
printf("使用网卡: %s\n", iface);
pcap_t *handle = pcap_open_live(iface, 65536, 1, 1000, errbuf);
if(!handle) {
fprintf(stderr, "pcap_open_live failed on %s: %s\n", iface, errbuf);
fprintf(stderr, "请检查网卡名称是否正确,或尝试使用 'any'\n");
return 1;
}
link_offset = get_link_offset(handle);
// 构建 BPF 过滤器
char filter_exp[2048] = "tcp and (";
for(int i = 0; i < target_count; i++) {
char tmp[64];
snprintf(tmp, sizeof(tmp), "host %s and port %d", targets[i].ip, targets[i].port);
if (i > 0) strcat(filter_exp, " or ");
strcat(filter_exp, tmp);
}
strcat(filter_exp, ")");
printf("使用过滤器: %s\n", filter_exp);
struct bpf_program fp;
if(pcap_compile(handle, &fp, filter_exp, 1, PCAP_NETMASK_UNKNOWN) == -1) {
fprintf(stderr, "pcap_compile failed: %s\n", pcap_geterr(handle));
pcap_close(handle);
return 1;
}
if(pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "pcap_setfilter failed: %s\n", pcap_geterr(handle));
pcap_close(handle);
return 1;
}
printf("开始监控 %d 个目标,采样间隔: %d 秒...\n", target_count, INTERVAL);
printf("按 Ctrl+C 停止监控\n\n");
sleep(2);
int sample_num = 0;
unsigned long long prev_sent[TARGET_MAX], prev_recv[TARGET_MAX];
for(int i = 0; i < target_count; i++) {
prev_sent[i] = targets[i].bytes_sent;
prev_recv[i] = targets[i].bytes_recv;
}
while(running) {
sample_num++;
time_t start = time(NULL);
while(time(NULL) - start < INTERVAL && running) {
int ret = pcap_dispatch(handle, 100, packet_handler, NULL);
if (ret == -1) {
fprintf(stderr, "pcap_dispatch error: %s\n", pcap_geterr(handle));
break;
}
usleep(1000);
}
if (!running) break;
for(int i = 0; i < target_count; i++) {
unsigned long long sent_diff = targets[i].bytes_sent - prev_sent[i];
unsigned long long recv_diff = targets[i].bytes_recv - prev_recv[i];
targets[i].send_mbps = (sent_diff * 8.0) / INTERVAL / 1000000.0;
targets[i].recv_mbps = (recv_diff * 8.0) / INTERVAL / 1000000.0;
prev_sent[i] = targets[i].bytes_sent;
prev_recv[i] = targets[i].bytes_recv;
}
print_header();
print_stats();
if (SAMPLE_COUNT > 0 && sample_num >= SAMPLE_COUNT) {
break;
}
}
pcap_close(handle);
printf("\n监控已停止。共采样 %d 次。\n", sample_num);
return 0;
}