Linux下C/C++实现(网络流量分析-NTA)

news2024/9/20 16:51:40

网络流量分析(NTA - Network Traffic Analysis) 就是捕捉网络中流动的数据包,并通过查看包内部数据以及进行相关的协议、流量、分析、统计等,协助发现网络运行过程中出现的问题。通过监控和分析网络环境中的流量,来判断流量是用在哪个系统或者哪个应用,并对流量做相应的分析统计。

网络流量分析解决方案用于监控企业网络。公司利用网络流量分析来记录和分析网络流量和资产间通信的模式。这些数据随后被用于发现和应对安全威胁。网络流量分析跟踪网络可用性和活动,并识别操作和安全方面的违规行为。

网络流量类型

为了更好地管理带宽,网络管理员决定路由器和交换机等网络设备如何处理某些类型的流量。网络流量一般分为两类:实时流量和非实时流量。

实时流量:

被视为对业务运营重要或关键的流量必须以尽可能高的质量按时交付。实时网络流量的示例包括VoIP、视频会议和网络浏览。

非实时流量:

也称为尽力而为流量,是网络管理员认为不如实时流量重要的流量。示例包括用于网络发布和电子邮件应用程序的文件传输协议(FTP)。

为什么网络流量分析和监控很重要

密切关注你的网络周边一种很好的做法。即使有强大的防火墙,错误也可能发生,恶意流量也可能通过。用户还可以利用隧道、外部匿名器和VPN等方法绕过防火墙规则。

此外,近年来勒索软件作为一种常见攻击类型的兴起,使得网络流量监控变得更加重要。

远程桌面协议(RDP)是另一个常见的目标应用程序。请确保阻止防火墙上的任何入站连接尝试。监控防火墙内的流量可以使您验证规则,获得有价值的见解,还可以用作基于网络流量的警报来源。

注意与Telnet等管理协议相关的任何可疑活动。由于Telnet是一种未加密的协议,会话流量将显示适用于设备品牌和型号的命令行界面(CLI)命令序列。CLI字符串可能会显示登录过程、用户凭据的显示、显示启动或运行配置的命令、复制文件等。请确保检查网络数据中是否有任何运行未加密管理协议的设备,例如:

1.Telnet(远程登录)
2.超文本传输协议(HTTP,端口80)
3.简单网络管理协议(SNMP,端口161/162)

分析和监控网络流量的目的是什么?

通过在网络边缘和网络核心实现网络流量分析,可以研究许多操作和安全问题。使用流量分析工具,您可以发现大量下载、流媒体或可疑的入站或出站流量。确保您从监控防火墙的内部接口开始,这将允许您跟踪特定客户端或用户的活动。

NTA还为组织提供了在端点之外对其网络上的威胁的更多可见性。随着移动设备、物联网设备、智能电视等的兴起,你需要的不仅仅是来自防火墙的日志,而是更智能的东西。当网络受到攻击时,防火墙日志也会出现问题。您可能会发现,由于防火墙上的资源负载,它们无法访问,或者它们被覆盖(有时甚至被黑客修改),导致重要的取证信息丢失。

Linux监控网络流量分析

Linux 内核提供了一种通过 /proc 文件系统,在运行时访问内核内部数据结构、改变内核设置的机制。proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。

用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。/proc文件系统中包含了很多目录,其中/proc/net/dev 保存了网络适配器及统计信息。

  • /proc/net/dev


bytes: 接口发送或接收的数据的总字节数
packets: 接口发送或接收的数据包总数
errs: 由设备驱动程序检测到的发送或接收错误的总数
drop: 设备驱动程序丢弃的数据包总数
fifo: FIFO缓冲区错误的数量
frame: 分组帧错误的数量
colls: 接口上检测到的冲突数
compressed: 设备驱动程序发送或接收的压缩数据包数
carrier: 由设备驱动程序检测到的载波损耗的数量
multicast: 设备驱动程序发送或接收的多播帧数

  • /proc/net/snmp

简单网络管理协议(SNMP)是一种网络协议,用于管理和监控互联网协议网络中的网络连接设备。提供了主机各层的IP、ICMP、ICMPMsg、TCP、UDP详细数据

  • /proc/net/netstat

/proc/net/netstat 提供了主机的收发包数、收包字节数据。

在查看centos机器的网络状态时,尝尝要看看计数器文件/proc/net/netstat,但是直接cat,如下显示

上面这个太难看懂,有如下awk脚本,可以格式化

cat /proc/net/netstat |  awk '(f==0) {name=$1; i=2; while ( i<=NF) {n[i] = $i; i++ }; f=1; next} (f==1){ i=2; while ( i<=NF){ printf "%s%s = %d\n", name, n[i], $i; i++}; f=0} ' 


Linux下C/C++实现(网络流量分析-NTA)


static int split_ifname(char *if_name, char *drv, uint32_t *instance)
{
	char *p;
	int n, m;

	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);
	return (B_TRUE);
}

static void diag(int use_errno, char *format, ...)
{
	va_list ap;
	char *error_str;

	(void) fprintf(stderr, "%s: ", g_progname);
	if (use_errno) 
	{
		error_str = strerror(errno);
		if (! error_str)
			error_str = strerror(0);
	}
	va_start(ap, format);
	(void) vfprintf(stderr, format, ap);
	va_end(ap);
	if (use_errno)
		(void) fprintf(stderr, ": %s\n", error_str);
	else
		(void) fputc('\n', stderr);
}

#define	die(...) \
do { \
	diag(__VA_ARGS__);			\
	exit(2);				\
} while (0)

static void update_stats(int net_dev)
{


...
	if (lseek(net_dev, 0, SEEK_SET) != 0)
		die(1, "lseek: %s", PROC_NET_DEV_PATH);
	bufsiz = 0;
	while ((n = read(net_dev, (void *) proc_net_buffer + bufsiz, sizeof(proc_net_buffer) - bufsiz)) > 0) 
	{
	    bufsiz += n;
	}
	if (bufsiz < 0)
		die(1, "read: %s", PROC_NET_DEV_PATH);
	else if (bufsiz < 200)
		die(0, "%s: invalid format\n", PROC_NET_DEV_PATH);

...

	/* 终止我们的字符串 */
	bufp = proc_net_buffer + 200;
	buf_remain = bufsiz - 200;
	bufp[buf_remain + 1] = '\0';

	gettimeofday(&now_tv, NULL);

	skip_to_newline = 0;
	g_nicdata_count = 0;
	lastp = NULL;
	while (*bufp) 
	{
		if (skip_to_newline) 
		{
			/* 需要跳过以前的数据 */
			for (; *bufp; bufp++)
				if (*bufp == '\n') 
				{
					bufp++;
					break;
			}
			if (! *bufp)
				break;
		}
		skip_to_newline = 1;

		/* 获取接口名称 */
		while (*bufp == ' ')
			bufp++;
		/* 检查格式 */
		n = strcspn(bufp, ":");
		if (n >= sizeof (if_name))
			die(0, "%s: interface name too long",
				PROC_NET_DEV_PATH);
		(void) strncpy(if_name, bufp, n);
		if_name[n] = '\0';
...
		loopback = streql("lo", if_name);
		if (g_nonlocal && loopback)
			continue;

		bufp += n + 1;
		ret = sscanf(bufp, "%llu %llu %llu %llu %llu %llu %llu"
			" %llu %llu %llu %llu %llu %llu %llu %llu %llu\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], &ll[14], &ll[15]);
		if (ret != 16)
			die(0, "%s: invalid format", PROC_NET_DEV_PATH);
		/* 如果从未看到数据包,则跳过接口 */
		if (ll[1] == 0 && ll[9] == 0)
			continue;

		g_nicdata_count++;
		nicp = find_nicdatap(&g_nicdatap, &lastp, if_name);
		nicp->new.tv.tv_sec = now_tv.tv_sec;
		nicp->new.tv.tv_usec = now_tv.tv_usec;
		nicp->new.rbytes = ll[0];
		nicp->new.rpackets = ll[1];
		nicp->new.wbytes = ll[8];
		nicp->new.wpackets = ll[9];
		nicp->new.sat = ll[2];
		nicp->new.sat += ll[3];
		nicp->new.sat += ll[11];
		nicp->new.sat += ll[12];
		nicp->new.sat += ll[13];
		nicp->new.sat += ll[14];
		if (g_opt_x) {
			nicp->new.ierr = ll[2];
			nicp->new.oerr = ll[10];
			nicp->new.coll = ll[13];
		}
		if (loopback)
			nicp->flags |= NIC_LOOPBACK;
		get_speed_duplex(nicp);
		nicp->report = 1;
	}
	if (g_tcp || g_udp)
		load_snmp(g_snmp);
	if (g_tcp) 
	{
		g_tcp_new->tv = now_tv;
		load_netstat(g_netstat);
	}
	if (g_udp)
		g_udp_new->tv = now_tv;
}

...

static void load_netstat(FILE *netstat)
{
...

	if (fseek(netstat, 0, SEEK_SET) != 0)
		die(1, "fseek: %s", PROC_NET_NETSTAT_PATH);
	remaining = 1;
	while (remaining) 
	{
		p = fgets(buf, sizeof (buf), netstat);
		if (! p)
			break;
		if (g_tcp && strncmp("TcpExt: SyncookiesSent SyncookiesRecv "
		    "SyncookiesFailed EmbryonicRsts PruneCalled RcvPruned "
		    "OfoPruned OutOfWindowIcmps LockDroppedIcmps "
		    "ArpFilter TW TWRecycled TWKilled PAWSPassive "
		    "PAWSActive PAWSEstab DelayedACKs DelayedACKLocked "
		    "DelayedACKLost ListenOverflows ListenDrops ",
		    p, 273) == 0) 
		  {
			/* We are after field 20 and 21 */
			int n = fscanf(netstat, "TcpExt: %*d %*d %*d "
				"%*d %*d %*d %*d %*d %*d %*d "
				"%*d %*d %*d %*d %*d %*d %*d "
				"%*d %*d %lld %lld ",
				&ll[0], &ll[1]);
			if (n == 2)
				g_tcp_new->listenDrop = ll[0] + ll[1];
			remaining--;
		}
	}
}


/*
获取TCP和UDP统计信息
*/

static void load_snmp(FILE *snmp)
{
..

	/* 从/proc/net/snmp加载TCP和/或UDP统计信息 */
	if (fseek(snmp, 0, SEEK_SET) != 0)
		die(1, "fseek: %s", PROC_NET_SNMP_PATH);
	remaining = 0;
	if (g_tcp)
		remaining++;
	if (g_udp)
		remaining++;
	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];
				...
				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 print_header(void)
{
...
	switch (g_style) 
	{
	case STYLE_SUMMARY:
		(void) printf("%8s %8s %14s %14s\n",
		    "Time", "Int", g_runit_1, g_wunit_1);
		break;
	case STYLE_FULL:
		(void) printf("%8s %8s %7s %7s %7s "
		    "%7s %7s %7s %5s %6s\n",
		    "Time", "Int", g_runit_1, g_wunit_1, "rPk/s",
		    "wPk/s", "rAvs", "wAvs", "%Util", "Sat");
		break;
	case STYLE_FULL_UTIL:
		(void) printf("%8s %8s %7s %7s %7s "
		    "%7s %7s %7s %6s %6s\n",
		    "Time", "Int", g_runit_1, g_wunit_1, "rPk/s",
		    "wPk/s", "rAvs", "wAvs", "%rUtil", "%wUtil");
		break;
	case STYLE_EXTENDED:
		update_timestr(NULL);
		(void) printf("%-10s %7s %7s %7s %7s  "
		    "%5s %5s %5s %5s %5s  %5s\n",
		    g_timestr, g_runit_2, g_wunit_2, "RdPkt", "WrPkt",
		    "IErr", "OErr", "Coll", "NoCP", "Defer", "%Util");
		break;
	case STYLE_EXTENDED_UTIL:
		update_timestr(NULL);
		(void) printf("%-10s %7s %7s %7s %7s  "
		    "%5s %5s %5s %5s %5s %6s %6s\n",
		    g_timestr, g_runit_2, g_wunit_2, "RdPkt", "WrPkt",
		    "IErr", "OErr", "Coll", "NoCP", "Defer",
		    "%rUtil", "%wUtil");
		break;
	}
}

...

运行结果:

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

  • 查看tcp相关信息

    InKB : 表示每秒接收到的千字节.
    OutKB : 表示每秒传输的千字节.
    InSeg : 表示每秒接收到的TCP数据段(TCP Segments).
    OutSeg : 表示每秒传输的TCP数据段(TCP Segments).
    Reset : 表示TCP连接从ESTABLISHED或CLOSE-WAIT状态直接转变为CLOSED状态的次数.
    AttF : 表示TCP连接从SYN-SENT或SYN-RCVD状态直接转变为CLOSED状态的次数,再加上TCP连接从SYN-RCVD状态直接转变为LISTEN状态的次数
    %ReTX : 表示TCP数据段(TCP Segments)重传的百分比.即传输的TCP数据段包含有一个或多个之前传输的八位字节.
    InConn : 表示TCP连接从LISTEN状态直接转变为SYN-RCVD状态的次数.
    OutCon : 表示TCP连接从CLOSED状态直接转变为SYN-SENT状态的次数.
    Drops : 表示从完成连接(completed connection)的队列和未完成连接(incomplete connection)的队列中丢弃的连接次数.

  • 查看udp相关信息

    InDG : 每秒接收到的UDP数据报(UDP Datagrams)
    OutDG : 每秒传输的UDP数据报(UDP Datagrams)
    InErr : 接收到的因包含错误而不能被处理的数据包
    OutErr :因错误而不能成功传输的数据包.

  • 查看网卡速度

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

总结

网络流量分析解决方案领先于其他网络安全工具,如入侵检测系统(IDS)、入侵防御系统(IPS)和防火墙。虽然这些工具主要关注网络周边的流量,但网络流量分析分析所有类型的网络通信,包括传统的TCP/IP数据包、云流量、虚拟网络流量以及API和SaaS交互。

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

参考:https://man7.org/linux/man-pages/man5/proc.5.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/453857.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

electron编译环境搭建和第一个桌面应用例子

前言 Electron是基于Chromium和Node.js实现的&#xff0c;所以开发人员所需要使用到的前端技术主要包括以下方面&#xff1a; 1、Html、CSS、JavaScript、ES6 2、前端开发工具Vue、Angular、React等的一种 3、其他网络、缓存、通讯、系统、跟踪等前端技术 4、对Vscode编辑…

SpringCloud --- 认识微服务、服务拆分和远程调用

一、认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.1、单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;…

C++学习(day5)

文章目录 一. 静态成员变量和函数(static)1. 静态成员变量2. 静态成员函数 二. 类的继承&#xff08;inhert&#xff09;1. 继承2. 继承的作用3. 一个类B继承类A4. 继承格式5. 子类会继承父类的所有成员6. 当父子类中出现同名的成员时7. **继承中构造函数和析构函数调用顺序**8…

反垃圾邮件产品测试评价方法示意图

声明 本文是学习信息安全技术 反垃圾邮件产品技术要求和测试评价方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 反垃圾邮件产品测试评价方法 测试环境 反垃圾邮件产品的典型测试环境如图1所示。 图1 反垃圾邮件产品典型测试环境示意图 测试设…

快速识别 SLI 指标的方法:VALET

SLI&#xff0c;Service Level Indicator&#xff0c;服务等级指标&#xff0c;其实就是我们选择哪些指标来衡量我们的稳定性。而 SLO&#xff0c;Service Level Objective&#xff0c;服务等级目标&#xff0c;指的就是我们设定的稳定性目标&#xff0c;比如“几个 9”这样的目…

Android音视频开发-OpenGL ES正交投影实现方法

本文实例为大家分享了OpenGL ES正交投影展示的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下 绘制正方形 在最开始绘制的六边形里面好像看起来挺容易的&#xff0c;也没有出现什么问题&#xff0c;接下来不妨忘记前面绘制六边形的代码&#xff0c;让我们按照自己的…

设计模式——组件协作模式之模板方法模式

文章目录 前言一、“组件协作” 模式二、模板方法模式1、动机2、源码分析讲解①、结构化软件设计②、面向对象软件设计 三、模板方法模式定义四、结构要点总结 前言 一、“组件协作” 模式 现代软件专业分工之后的第一个结果是 “框架与应用程序的划分”&#xff0c;“组件协作…

部署LVS-NAT群集实验

一、 实验准备 负载调度器&#xff1a;内网关 ens33&#xff1a;192.168.109.12&#xff0c;外网关 ens37&#xff1a;12.0.0.1外网 Web节点服务器1&#xff1a;192.168.109.13 Web节点服务器2&#xff1a;192.168.109.14 NFS服务器&#xff1a;192.168.109.11 客户端&#xf…

C#基础学习--其他主题

目录 概述 字符串 使用StringBuilder类 把字符串解析为数据值 关于可空类型的更多内容 为可空类型赋值 使用空接合运算符 Main方法 文档注释 嵌套类型 析构函数和dispose模式 概述 再本章中会讲解一些重要的杂项知识 字符串 字符串是Unicode字符串数组 字符串是不可…

ISO-27145故障诊断说明

ISO-27145故障诊断说明 2.1 27145目录说明 ISO27145-1: 这里边介绍的是一般信息和用例定义&#xff1b; ISO27145-2: 这里边介绍的是与排放相关的通用数据规则&#xff0c;用于查询&#xff1b; ISO27145-3: 这里边主要介绍了支持的服务 12服务 14服务 19服务 22服务 31服务&…

【移动端网页布局】移动端网页布局基础概念 ⑧ ( 移动端页面布局方案 | 单独制作的移动端页面 - 主流 | 响应式页面兼容移动端 - 开发难度较大 )

文章目录 一、移动端页面布局方案1、单独制作的移动端页面2、响应式页面兼容移动端 一、移动端页面布局方案 移动端页面方案 : 单独制作的移动端页面 : 主流开发方案 , PC 端 与 移动端 访问的是不同的页面 , 目前的 京东 / 淘宝 等电商网站移动端页面采取的该方案 ;响应式页面…

高效编程----VSCode+ChatGPT插件

VSCode中使用ChatGPT插件 首先在VSCode中打开扩展面板&#xff0c;搜索ChatGPT&#xff0c;安装蓝色圈出插件&#xff0c;如图所示&#xff1a; 安装完成后&#xff0c;需要重启VSCode 注册账号&#xff0c;如图所示&#xff1a; 然后在ChatGPT对话框中输入信息即可使用&#…

[oeasy]python0137_相加运算_python之禅_import_this_显式转化

变量类型 相加运算 回忆上次内容 上次讲了是从键盘输入变量input 函数 可以有提示字符串需要有具体的变量接收输入的字符串 输入单个变量没有问题 但是输入两个变量之后一相加就非常离谱 怎么办呢&#xff1f;&#x1f914; 基本实验 回到 游乐场 做个 实验 两个整数 相加…

C++STL——map与set的模拟实现

map与set的模拟实现 map与set的部分源码参考改造红黑树红黑树的迭代器补全set与map的实现完整代码 map与set的部分源码参考 map和set的底层都是由红黑树实现的。 所以这里将上次实现的红黑树插入拿来用。 首先想一想&#xff0c;搜索二叉树不能修改值&#xff0c;因为会破坏整…

第十章 装饰者模式

文章目录 前言一、装饰者模式定义装饰者模式 UML图 二、装饰者模式解决星巴克咖啡订单完整代码Drink 抽象 饮料类Coffee 咖啡类继承 Drink 做一个缓冲层Espresso 意大利咖啡 继承 CoffeeLongBlack 咖啡ShortBlack 咖啡装饰者&#xff0c;调料牛奶巧克力豆浆咖啡店测试程序添加 …

01-yolo算法

要点&#xff1a; 归纳 YOLOv5 github 1 YOLO v1 1) 将一幅图像分成SxS个网格(grid cell)&#xff0c;如果某个object的中心 落在这个网格中&#xff0c;则这个网格就负责预测这个object。 2)每个网格要预测B个bounding box&#xff0c;每个bounding box 除了要预测位置之…

TortoiseSVN使用-合并分支代码

文章目录 3.4.12 合并分支代码TortoiseSVN有2种合并方式演示场景1&#xff1a;&#xff08;合并一个版本范围 Merge a range of revisions&#xff09;演示场景2&#xff1a;&#xff08;合并两个不同的树 Merge two different trees&#xff09;&#xff0c;不设置主分支版本演…

初窥Edubuntu 23.04:装有教育软件的Ubuntu桌面

导读4月20日&#xff0c;Edubuntu将作为Ubuntu官方口味卷土重来&#xff0c;作为即将发布的Ubuntu 23.04&#xff08;Lunar Lobster&#xff09;的一部分&#xff0c;所以我认为让你们先看看这个重制版中包含的内容是个好主意。 Edubuntu以前被称为Ubuntu教育版&#xff0c;最…

Anaconda安装及tensorflow安装

1.下载Anaconda安装包&#xff0c;并安装好 官网下载网址&#xff1a;https://www.anaconda.com/download/ 清华映像站&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 注意&#xff1a;注意安装anaconda时一定要把环境变量加入windows环境中。若没有…

C语言---函数介绍详解

生活的全部意义在于无穷地探索尚未知道的东西,在于不断地增加更多的知识——左拉 文章目录 前言函数模块化程序设计方法函数的定义函数的分类函数定义角度库函数自定义函数 函数形式角度无参函数有参函数 函数兼有其他语言中的函数和过程两种功能的角度有返回值函数无返回值函…