Linux C/C++ 实现网络流量分析(性能工具)_网络流量分析代码-程序员宅基地

技术标签: 网络流量  C/C++  c++  c语言  linux  性能工具  

网络流量分析的原理基于对数据包的捕获、解析和统计分析,通过对网络流量的细致观察和分析,帮助管理员了解和优化网络的性能、提高网络安全性,并快速排查和解决网络故障和问题。

Linux中的网络流量常见类型
在Linux中,网络流量可以分为几种不同的类型。以下是一些常见的网络流量类型:

  1. TCP流量:TCP(传输控制协议)是一种可靠的、面向连接的协议。TCP流量通常用于传输可靠的数据,例如网页浏览、文件传输等。

  2. UDP流量:UDP(用户数据报协议)是一种无连接的协议,不保证数据的可靠性和顺序。UDP流量通常用于实时应用,如VoIP(网络电话)、视频流传输等。

  3. ICMP流量:ICMP(Internet控制消息协议)用于传输网络控制消息和错误报告。ICMP流量通常用于网络故障排查、Ping命令等。

  4. HTTP流量:HTTP(超文本传输协议)是一种应用层协议,用于在Web浏览器和服务器之间传输数据。HTTP流量通常用于网页浏览、下载文件等Web应用。

  5. HTTPS流量:HTTPS是HTTP的安全版本,使用SSL(安全套接字层)或TLS(传输层安全)协议加密通信。HTTPS流量通常用于安全的Web传输,例如在线银行、电子商务等。

  6. DNS流量:DNS(域名系统)用于将域名与IP地址相互映射。DNS流量通常用于解析域名、获取IP地址等。

  7. FTP流量:FTP(文件传输协议)用于在客户端和服务器之间传输文件。FTP流量通常用于文件上传、下载等。

  8. SSH流量:SSH(安全壳层)是一种加密的网络协议,用于安全和远程登录。SSH流量通常用于安全的远程管理和文件传输。

这些网络流量类型在不同的应用场景和协议中扮演着不同的角色。分析和监控不同类型的网络流量可以帮助管理员了解网络使用情况、排查故障并优化网络性能。

Linux下监控网络流量的目的
Linux下监控网络流量的目的有多个:

  1. 网络性能优化:监控网络流量可以帮助管理员了解网络的使用情况和瓶颈,以便进行性能优化和提高网络效率。

  2. 安全性增强:通过监控网络流量,可以及时发现异常的网络流量,如DDoS攻击、恶意软件传播等,以便及时采取相应的防御措施。

  3. 资源管理:监控网络流量可以帮助管理员了解各个主机或设备的网络使用情况,对网络资源进行分配和管理,以避免某个用户或设备占用过多的带宽和资源导致其他用户或设备受到影响。

  4. 计费和成本控制:监控网络流量可以帮助提供网络服务的机构或企业对用户的网络使用情况进行计费和成本控制,确保网络资源的合理利用和节约成本。

  5. 故障排查和问题定位:通过监控网络流量,可以及时发现网络故障、问题和异常,辅助管理员进行故障排除和问题定位,以减少网络停机时间和降低维护成本。

总而言之,监控网络流量可以提高网络性能、保障网络安全、管理网络资源、控制成本和故障排查,对于维护良好的网络运行非常重要。

有哪些专门的工具和技术分析网络流量

要实现Linux上的网络流量分析,可以使用一些专门的工具和技术。下面是一些常用的方法和原理:

  1. 使用抓包工具:在Linux上,可以使用像tcpdump、Wireshark这样的抓包工具来捕获网络数据包。这些工具可以监听网络接口,并将捕获到的数据包保存到文件中进行分析。

  2. 使用流量监控工具:像ntop、iftop、bmon等工具可以实时监控网络接口的流量情况,并提供统计信息和图形化展示。

  3. 分析捕获的数据包:捕获到的数据包可以使用Wireshark等工具进行解析和分析。Wireshark可以显示捕获的数据包的详细信息,如源IP地址、目的IP地址、协议类型、端口等,并提供过滤机制来筛选感兴趣的数据。

  4. 使用流量分析工具:除了抓包工具和流量监控工具,还有一些专门用于网络流量分析的工具,如tcpflow、Bro等。这些工具可以解析并分析网络流量中的各种协议,提供更深入的网络流量分析功能。

这些工具的实现原理都涉及到网络协议、socket编程、数据包的捕获和解析等知识。具体来说,抓包工具通过监听网络接口,将接收到的数据包保存到文件中;流量监控工具通过读取接口的流量数据并进行统计和展示;数据包分析工具和流量分析工具则依靠网络协议和数据包的解析来提供更深入的分析功能。

总体来说,实现网络流量分析需要一定的网络知识和编程技巧,同时需要使用相关工具和技术进行数据的捕获、解析和分析。

在Linux文件系统的/proc目录下分析网络流量

在Linux文件系统的/proc目录下,可以找到一些与网络流量相关的信息。以下是一些常见的文件和目录:

  1. /proc/net/dev:这个文件提供了网络设备的收发网络流量统计信息,包括每个网络接口的接收和发送数据包数量、错误统计、丢弃的数据包数量等。
    使用cat或者less命令:你可以使用cat或者less命令来查看/proc下的文件内容,例如:cat /proc/net/dev可以查看网络设备的收发网络流量统计信息。
    使用awk或者sed命令进一步处理:你可以使用awk或者sed命令来处理和过滤数据,例如:cat /proc/net/dev | awk '{print $1, $2}'可以只打印出网络设备名称和接收流量的统计值.
    在这里插入图片描述

  2. /proc/net/tcp:这个文件提供了当前TCP连接的详细信息,包括本地和远程IP地址、端口号,连接状态,以及一些统计信息。
    使用grep命令筛选:你可以使用grep命令来筛选你感兴趣的信息,例如:grep "ESTABLISHED" /proc/net/tcp可以查看当前所有TCP连接中状态为ESTABLISHED的连接信息。

  3. /proc/net/udp:类似于/proc/net/tcp文件,提供了当前UDP连接的详细信息。

  4. /proc/net/raw:提供了当前原始套接字(RAW socket)的相关信息,包括本地和远程IP地址、协议类型等。

  5. /proc/net/snmp:提供了简单网络管理协议(SNMP)相关的统计信息,包括接口、IP、TCP、UDP等各层的统计信息。

  6. /proc/net/ip_conntrack:如果系统启用了连接跟踪(conntrack)功能,这个文件提供了关于当前连接的跟踪信息,包括连接状态、源IP地址、目的IP地址、端口号等。

这些文件提供了一些基本的网络流量统计和连接信息,可以通过读取这些文件进行分析和监控。想要更加深入和详细地分析网络流量,则需要使用更专业的网络流量分析工具。

Linux C/C++ 网络流量分析

代码中网络流量分析是一个用于网络统计的命令行工具,用于监视系统网络接口的流量、带宽使用情况以及与网络相关的统计数据。它可以提供网络传输的各种统计信息,包括数据包的数量、字节数、错误、丢包等。

/*
 * 接口统计信息
 */
typedef struct nic_stats {
    
	struct timeval tv;		/* tv_sec, tv_usec */
	uint64_t rbytes;		/* total read bytes */
	uint64_t wbytes;		/* total written bytes */
	uint64_t rpackets;		/* total read packets */
	uint64_t wpackets;		/* total written packets */
	uint64_t ierr;			/* total input errors */
	uint64_t oerr;			/* total output errors */
	uint64_t coll;			/* total collisions */
	uint64_t nocp;			/* total nocanput */
	uint64_t defer;			/* total defers */
	uint64_t sat;			/* saturation value */
} nicstats_t;

/*
 * print_header - 打印标题行
 */
static void
print_header(void)
{
    
	if (g_style)
		(void) printf("%8s %5s %14s %14s\n",
		    "Time", "Int", "rKb/s", "wKb/s");
	else
		(void) printf(
		    "%8s %5s %7s %7s %7s %7s %7s %7s %7s %7s\n",
		    "Time", "Int", "rKb/s", "wKb/s", "rPk/s",
		    "wPk/s", "rAvs", "wAvs", "%Util", "Sat");
}

static int split_ifname(char *if_name, char *drv, uint32_t *instance)
{
    
...
	n = 0;
	for (p = if_name; *p; p++)
		n++;
	if (n <= 1)
		return (B_FALSE);
	m = n;
	for (p--; isdigit(*p); p--)
		n--;
	if (m == n || n == 0)
		return (B_FALSE);
	(void) strncpy(drv, if_name, n);
	drv[n] = '\0';
	*instance = (uint32_t)atol(++p);
...
}
...
static void update_ksp_by_type(kstat_t **kspp, uint32_t types, char *name)
{
    
...

	if (types & KS_LINK) 
	{
    
		*kspp = fetch_ksp("link", 0, name);
		return;
	}
	(void) split_ifname(name, drv, &instance);
	if (types & KS_DRV_MAC) 
	{
    
		*kspp = fetch_ksp(drv, instance, "mac");
		return;
	}
	if (types & KS_DIN) 
	{
    
		*kspp = fetch_ksp(drv, instance, name);
		return;
	}
	if (types & KS_DRV) {
    
		*kspp = fetch_ksp(drv, instance, NULL);
		return;
	}
	if (types & KS_NAME) {
    
		*kspp = fetch_ksp(name, -1, NULL);
		return;
	}
	...
}
static void update_stats(void)
{
    
...

	(void) gettimeofday(&now_tv, NULL);

	if (g_tcp) 
	{
    
		/* 更新TCP统计信息 */
		if (g_new_kstat_chain) 
		{
    
			g_tcp_ksp = kstat_lookup(g_kc, "tcp", -1, "tcp");
			if (! g_tcp_ksp)
				die(1, "kstat_lookup");
		}
		if (kstat_read(g_kc, g_tcp_ksp, NULL) < 0)
			die(1, "kstat_read");
		g_tcp_new->tv.tv_sec = now_tv.tv_sec;
		g_tcp_new->tv.tv_usec = now_tv.tv_usec;
		TCP_UPDATE(inDataInorderSegs, "inDataInorderSegs");
		TCP_UPDATE(outDataSegs, "outDataSegs");
		TCP_UPDATE(inDataInorderBytes, "inDataInorderBytes");
		TCP_UPDATE(inDataUnorderSegs, "inDataUnorderSegs");
		TCP_UPDATE(inDataUnorderBytes, "inDataUnorderBytes");
		TCP_UPDATE(outDataBytes, "outDataBytes");
		TCP_UPDATE(estabResets, "estabResets");
		TCP_UPDATE(outRsts, "outRsts");
		TCP_UPDATE(attemptFails, "attemptFails");
		TCP_UPDATE(retransBytes, "retransBytes");
		TCP_UPDATE(passiveOpens, "passiveOpens");
		TCP_UPDATE(activeOpens, "activeOpens");
		TCP_UPDATE(halfOpenDrop, "halfOpenDrop");
		TCP_UPDATE(listenDrop, "listenDrop");
		TCP_UPDATE(listenDropQ0, "listenDropQ0");
	}
	if (g_udp) 
	{
    
		/* 更新UDP统计信息 */
		if (g_new_kstat_chain) 
		{
    
			g_udp_ksp = kstat_lookup(g_kc, "udp", -1, "udp");
			if (! g_udp_ksp)
				die(1, "kstat_lookup");
		}
		if (kstat_read(g_kc, g_udp_ksp, NULL) < 0)
			die(1, "kstat_read");
		g_udp_new->tv.tv_sec = now_tv.tv_sec;
		g_udp_new->tv.tv_usec = now_tv.tv_usec;
		UDP_UPDATE(inDatagrams, "inDatagrams");
		UDP_UPDATE(outDatagrams, "outDatagrams");
		UDP_UPDATE(inErrors, "inErrors");
		UDP_UPDATE(outErrors, "outErrors");
	}

	if (g_style == STYLE_NONE && ! g_list)
		return;

	/* 更新接口统计信息 */
	for (nicp = g_nicdatap; nicp; nicp = nicp->next) 
	{
    
		if (! (nicp->flags & NIC_UP))
			/* 链接未打开 */
			continue;
		if (g_nonlocal && (nicp->flags & NIC_LOOPBACK))
			continue;
		if (! (nicp->flags & NIC_OK_UPDATED))
			if (kstat_read(g_kc, nicp->op_ksp, NULL) < 0)
				die(1, "kstat_read");
		/* 保存网络值 */
		nicp->new.tv.tv_sec = now_tv.tv_sec;
		nicp->new.tv.tv_usec = now_tv.tv_usec;
		nicp->new.rbytes =
			fetch6432(nicp->op_ksp, "rbytes64", "rbytes", 0);
		nicp->new.wbytes =
			fetch6432(nicp->op_ksp, "obytes64", "obytes", 0);
		nicp->new.rpackets =
			fetch6432(nicp->op_ksp, "ipackets64", "ipackets", 0);
		nicp->new.wpackets =
			fetch6432(nicp->op_ksp, "opackets64", "opackets", 0);
		switch (g_style) 
		{
    
		case STYLE_EXTENDED_PARSEABLE:
		case STYLE_EXTENDED:
			nicp->new.ierr = fetch32(nicp->op_ksp, "ierrors", 0);
			nicp->new.oerr = fetch32(nicp->op_ksp, "oerrors", 0);
			/*FALLTHROUGH*/
		case STYLE_FULL:
		case STYLE_SUMMARY:
			nicp->new.coll = fetch32(nicp->op_ksp, "collisions",
				0);
			nicp->new.nocp = fetch_nocanput(nicp->op_ksp, 0);
			nicp->new.defer = fetch32(nicp->op_ksp, "defer_xmts",
				0);
			nicp->new.sat = nicp->new.defer + nicp->new.nocp +
				nicp->new.coll;
			nicp->new.sat += fetch32(nicp->op_ksp, "noxmtbuf", 0);
			break;
		}
		nicp->speed = fetch64(nicp->op_ksp, "ifspeed", 0);
		nicp->duplex = fetch32(nicp->op_ksp, "link_duplex", 0);
	}
...
}
static void load_snmp(FILE *snmp)
{
    
...

	/* 从/proc/net/snmp加载TCP和/或UDP统计信息 */
...
	while (remaining) 
	{
    
		p = fgets(buf, sizeof (buf), snmp);
		if (! p)
			break;
		if (g_tcp && strncmp("Tcp: RtoAlgorithm RtoMin RtoMax MaxConn "
				"ActiveOpens PassiveOpens AttemptFails "
				"EstabResets CurrEstab InSegs OutSegs "
				"RetransSegs InErrs OutRsts", p, 141) == 0) 
				{
    
			int n;
			n = fscanf(snmp, "Tcp: %lld %lld %lld %lld "
			    "%lld %lld %lld %lld %lld %lld "
			    "%lld %lld %lld %lld\n",
			    &ll[0], &ll[1], &ll[2], &ll[3],
			    &ll[4], &ll[5], &ll[6], &ll[7],
			    &ll[8], &ll[9], &ll[10], &ll[11],
			    &ll[12], &ll[13]);
			if (n == 14) 
			{
    
				g_tcp_new->inDataInorderSegs = ll[9];
				g_tcp_new->outDataSegs = ll[10];
				g_tcp_new->estabResets = ll[7];
				g_tcp_new->outRsts = ll[13];
				g_tcp_new->attemptFails = ll[6];
				/* Note: bytes */
				g_tcp_new->retransBytes = ll[11];
				g_tcp_new->passiveOpens = ll[5];
				g_tcp_new->activeOpens = ll[4];
			}
			remaining--;
		} 
		else if (g_udp && strncmp("Udp: InDatagrams NoPorts "
				"InErrors OutDatagrams RcvbufErrors "
				"SndbufErrors\n", p, 72) == 0) 
				{
    
			int n;
			n = fscanf(snmp, "Udp: %lld %lld %lld %lld "
			    "%lld %lld\n",
			    &ll[0], &ll[1], &ll[2], &ll[3],
			    &ll[4], &ll[5]);
			if (n == 6) 
			{
    
				g_udp_new->inDatagrams = ll[0];
				g_udp_new->outDatagrams = ll[3];
				g_udp_new->inErrors = ll[2]; /* + ll[4]? */
				g_udp_new->outErrors = ll[5];
			}
			remaining--;
		}
	}
}
...
static void update_timestr(time_t *tptr)
{
    
...

	if (tptr)
		t = *tptr;
	else
		t = time(NULL);
	tm = localtime(&t);
	(void) strftime(g_timestr, sizeof (g_timestr), "%H:%M:%S", tm);
}

static void sleep_for(hrtime_t period, hrtime_t start_n)
{
    
...
	do 
	{
    
		pause_tv.tv_sec = pause_n / NANOSEC;
		pause_tv.tv_nsec = pause_n % NANOSEC;
		status = nanosleep(&pause_tv, (struct timespec *)NULL);
		if (status < 0)
			if (errno == EINTR)
			 {
    
				now_n = gethrtime();
				pause_n = start_n + period - now_n;
				if (pause_n < 100)
					return;
			}
			 else 
			{
    
				...
			}
	} while (status != 0);
}
...

If you need the complete source code, please add the WeChat number (c17865354792)

运行结果:


Time列:表示当前采样的响应时间.
Int: 网卡名称.
rKB/s : 每秒接收到千字节数.
wKB/s : 每秒写的千字节数.
rPk/s : 每秒接收到的数据包数目.
wPk/s : 每秒写的数据包数目.
rAvs : 接收到的数据包平均大小.
wAvs : 传输的数据包平均大小.
%Util : 网卡利用率(百分比).
Sat : 网卡每秒的错误数.网卡是否接近饱满的一个指标.尝试去诊断网络问题的时候,推荐使用-x选项去查看更多的统计信息.

这将显示ens33接口的流量、带宽使用情况以及其他统计数据:
监控所有网络接口的统计信息,同时显示TCP和UDP连接相关的统计信息:

总结

网络流量分析需要一定的技术知识和经验,但通过学习和实践,我们可以掌握这个技能,更好地管理和维护网络环境。

Welcome to follow WeChat official account【程序猿编码

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chen1415886044/article/details/134093057

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签