当前位置: 首页 > article >正文

计算机网络实验课(二)——抓取网络数据包,并实现根据条件过滤抓取的以太网帧,分析帧结构

文章目录

  • 一、添加控件
  • 二、代码分析
    • 2.1 代码
    • 2.2 控件初始化
    • 2.3 打开和关闭设备
    • 2.4 开始和结束捕获
    • 2.5 设置捕获条件
    • 2.6 捕获数据包
  • 三、运行程序
  • 四、结果分析

提要:如果你通过vs打开.sln文件,然后代码界面或者前端界面都没找到,视图里面也没找到的话。我这里有个小技巧(启用调试,会出现代码界面,可能是主函数的部分,需要你对Form1这个函数点进去,就是一个你的代码文件了)
在这里插入图片描述
点击中间逐语句,出现program,然后再进入Form1
在这里插入图片描述

一、添加控件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、代码分析

①利用添加的若干个控件实现捕获数据包的条件过滤
②将捕获的数据包简单分析后显示到RichTextBox控件中

2.1 代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpPcap;
using PacketDotNet;
using SharpPcap.LibPcap;
using System.Net;
using System.IO;
namespace 实验教程
{// 协议类型public enum SnapProtocol : int{udp = 0,tcp = 1,arp = 2,rarp = 3,ip = 4}public partial class Form1 : Form{/// <summary>/// 全局私有变量/// </summary>CaptureDeviceList   device_list;         // 设备列表ICaptureDevice      device;              // 当前选择设备DelegateMethod      disp_info;           // 委托public Form1(){InitializeComponent();// 获得设备列表device_list = GetDeviceList();// 获取支持的协议列表LoadProto();// 载入所有网卡LoadDevice();// 显示数据包委托函数disp_info = new DelegateMethod(Disp_PacketInfo);}#region 程序初始化/// <summary>/// 获得当前的设备列表(网卡)/// </summary>/// <returns></returns>private CaptureDeviceList GetDeviceList(){// Print SharpPcap version string ver = SharpPcap.Version.VersionString;this.richTextBox1.Text = string.Format("SharpPcap {0}, Device List\n", ver);try{// Retrieve the device listCaptureDeviceList devices = CaptureDeviceList.Instance;// If no devices were found print an errorif (devices.Count < 1){this.richTextBox1.Text += "No devices were found on this machine\n";return null;}this.richTextBox1.Text += "\nThe following devices are available on this machine:\n";this.richTextBox1.Text += "----------------------------------------------------\n";// Print out the available network devicesforeach (ICaptureDevice dev in devices)this.richTextBox1.Text += string.Format("{0}\n", dev.ToString());return devices;}catch (System.Exception ex){MessageBox.Show(ex.ToString());return null;}}/// <summary>/// 获取支持的协议列表/// </summary>private void LoadProto(){comboBox2.Items.Clear();foreach (string e in Enum.GetNames(typeof(SnapProtocol))){comboBox2.Items.Add(e);}comboBox2.SelectedIndex = 0;}/// <summary>/// 载入所有网卡信息/// </summary>private void LoadDevice(){comboBox1.Items.Clear();if (device_list == null){MessageBox.Show("没有找到任何网卡设备!");return;}foreach (LibPcapLiveDevice dev in device_list){try{comboBox1.Items.Add(dev.Addresses[0].Addr);}catch{continue;}}comboBox1.SelectedIndex = 0;}#endregion/// <summary>/// 打开设备/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void button1_Click(object sender, EventArgs e){if (button1.Text == "打开设备"){button1.Text = "关闭设备";groupBox1.Enabled = false;device = device_list[comboBox1.SelectedIndex];device.OnPacketArrival += new SharpPcap.PacketArrivalEventHandler(device_OnPacketArrival);device.Open(DeviceMode.Promiscuous, 1000);device.Filter = RcvPacketFilter();device.StartCapture();}else{button1.Text = "打开设备";groupBox1.Enabled = true;try {device.StopCapture();}catch { device.Close();}}string result1 = @"C:\Users\19468\Desktop\\测试文件.txt";//结果保存到桌面FileStream fs = new FileStream(result1, FileMode.Append);StreamWriter wr = null;wr = new StreamWriter(fs);wr.WriteLine("测试!");wr.Close();}#region 捕获和显示函数/// <summary>/// 根据要求构造数据包过滤字符串/// </summary>private string RcvPacketFilter(){SnapProtocol proto = (SnapProtocol)comboBox2.SelectedIndex;IPAddress src_host, dst_host;string filter = proto.ToString();if ((textBox1.Text.Trim().Length > 0) && (IPAddress.TryParse(textBox1.Text, out src_host))){filter += string.Format(" and src host {0}", src_host.ToString());}if ((textBox2.Text.Trim().Length > 0) && (IPAddress.TryParse(textBox2.Text, out dst_host))){filter += string.Format(" and dst host {0}", dst_host.ToString());}return filter;}/// <summary>/// 抓包事件函数,在抓到符合条件的数据包的时候该函数将被调用/// 功能:///     1. 获得当前数据包的时间间隔、长度、协议类型、地址等参数///     2. 将信息输出到RichTextBox控件显示出来/// </summary>private void device_OnPacketArrival(object sender, CaptureEventArgs packet){// 时间和长度的获取DateTime time = packet.Packet.Timeval.Date;int len = packet.Packet.Data.Length;// 解析数据包成:IP包Packet p = Packet.ParsePacket(packet.Packet.LinkLayerType, packet.Packet.Data);IpPacket ip = (IpPacket)p.Extract(typeof(IpPacket));// 数据包信息string info = string.Format("\nsrc_addr={0}, des_addr={1}, type={2}\n",ip.SourceAddress, ip.DestinationAddress, ip.Protocol);info += string.Format("{0}:{1}:{2},{3} Len={4}\n",time.Hour, time.Minute, time.Second, time.Millisecond, len);info += string.Format(byteToHexStr(packet.Packet.Data));// 使用委托显示结果richTextBox1.Invoke(disp_info, info);}delegate void DelegateMethod(string info);/// <summary>/// 显示收到数据包的信息(由于捕获过程开辟了新线程,因此捕获结果需要委托来传递到RichTextBox)/// </summary>/// <param name="info"></param>private void Disp_PacketInfo(string info){richTextBox1.Text += info;}#endregion#region 字符串与byte数组相互转换/// <summary> /// 字节数组转16进制字符串 /// </summary> /// <param name="bytes"></param> /// <returns></returns> public static string byteToHexStr(byte[] bytes){string returnStr = "";if (bytes != null){for (int i = 0; i < bytes.Length; i++){returnStr += bytes[i].ToString("X2") + " ";}}return returnStr;}/// <summary> /// 字符串转16进制字节数组 /// </summary> /// <param name="hexString"></param> /// <returns></returns> public static byte[] strToToHexByte(string hexString){hexString = hexString.Replace(" ", "");if ((hexString.Length % 2) != 0)hexString += " ";byte[] returnBytes = new byte[hexString.Length / 2];for (int i = 0; i < returnBytes.Length; i++)returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);return returnBytes;}/// <summary>/// 字符串IP地址转换成byte数组/// </summary>/// <param name="decString"></param>/// <returns></returns>public static byte[] strIPToByte(string decString){string[] decStringArray = decString.Split('.');if (decStringArray.Length == 4){byte[] returnBytes = new byte[4];for (int i = 0; i < 4; i++){returnBytes[i] = Convert.ToByte(decStringArray[i]);}return returnBytes;}else{MessageBox.Show("IP地址格式错误!(参考:192.168.0.1)");return null;}}#endregion}
}

2.2 控件初始化

捕获设置中使用ComboBox选择网卡和协议类型。
其中,协议类型定义如下

// 协议类型
public enum SnapProtocol : int 
{ 
udp = 0, 
tcp = 1, 
arp = 2, 
rarp = 3, 
ip = 4 
} 

网卡信息则由实验一中的函数获得。现将这些选项填充到 ComboBox 中,这里使用两个函数来完成这两个ComboBox的初始化,即填充Item属性。函数的具体代码如下:

        /// <summary>/// 获取支持的协议列表/// </summary>private void LoadProto(){comboBox2.Items.Clear();foreach (string e in Enum.GetNames(typeof(SnapProtocol))){comboBox2.Items.Add(e);}comboBox2.SelectedIndex = 0;}/// <summary>/// 载入所有网卡信息/// </summary>private void LoadDevice(){comboBox1.Items.Clear();if (device_list == null){MessageBox.Show("没有找到任何网卡设备!");return;}foreach (LibPcapLiveDevice dev in device_list){try{comboBox1.Items.Add(dev.Addresses[0].Addr);}catch{continue;}}comboBox1.SelectedIndex = 0;}

这些内容是在程序一开始执行,因此同实验一中获得设备列表一样,这两个函数可以放在界面初始化以后执行,紧随GetDeviceList函数:

      public Form1(){InitializeComponent();// 获得设备列表device_list = GetDeviceList();// 获取支持的协议列表LoadProto();// 载入所有网卡LoadDevice();// 显示数据包委托函数disp_info = new DelegateMethod(Disp_PacketInfo);}

至此,控件的初始化就完成了,下面是实现功能的关键步骤。

2.3 打开和关闭设备

打开设备调用ICaptureDevice对象的Open函数实现,ICaptureDevice 对象则通过实验一获得的设备列表得到,方式如下:

ICaptureDevice device = device_list[i];

Open 函数有三个重载:
Open()
Open(DeviceMode mode)
Open(DeviceMode mode, int read_timeout)

mode 参数可选DeviceMode.NormalDeviceMode.Promiscuous,分别代表普通模式和混合模式。其中普通模式捕获到达本机或者从本机发出的数据包,忽略转发到其他终端的数据包;而混合模式将捕获所有到达网卡的数据包。
timeout 参数指示超时时间,单位为毫秒,设置为0表示不限制超时。

关闭设备使用Close函数即可。

在本项目中,打开和关闭由按钮控制,因此该按钮(button1)的Click事件函数编辑如下,特别注意黄色高亮部分:
在这里插入图片描述

        private void button1_Click(object sender, EventArgs e){if (button1.Text == "打开设备"){button1.Text = "关闭设备";groupBox1.Enabled = false;device = device_list[comboBox1.SelectedIndex];device.OnPacketArrival += new SharpPcap.PacketArrivalEventHandler(device_OnPacketArrival);device.Open(DeviceMode.Promiscuous, 1000);device.Filter = RcvPacketFilter();device.StartCapture();}else{button1.Text = "打开设备";groupBox1.Enabled = true;try {device.StopCapture();}catch { device.Close();}}

2.4 开始和结束捕获

在打开设备以后,捕获还未真正开始,捕获操作将调用专门的捕获函数后开始。捕获分为异步捕获和同步捕获,异步捕获需要注册事件 OnPacketArrival;而同步捕获只需要在打开设备以后调用函数 GetNextPacket,并且为了防止阻塞主线程,同步捕获通常需要开辟一个线程去实现。同步捕获方式参照下方链接文章说明:
SharpPcap - A Packet Capture Framework for .NET
本例程使用异步方式,基本流程为:
注册OnPacketArrival 事件——》StartCapture——》StopCapture。使用方式见上一节button1的Click事件灰色背景部分代码。

在StartCapture 执行后,一旦有符合条件的网络数据包到达网卡,被注册的事件函数(device_OnPacketArrival)就会执行,这一过程类似Button的Click事件的执行过程。

2.5 设置捕获条件

不对捕获的包进行条件过滤将捕获所有到达网卡的数据包是没有意义的。通常对网络封包进行分析需要能够根据封包的参数对收到的数据包进行过滤,从而快速定位到想要进行分析的封包。成熟的网络封包分析软件能够依据 IP、协议类型、端口、数据大小、通讯方向、数据内容等等一系列参数对封包进行过滤。 在SharpPcap 中,参数的过滤通过设置字符串表达式来实现,即,通过设置ICaptureDevice 对象的 Filter 属性来实现,例如:
string filter = "ip and tcp";
device.Filter = filter;
上述表达式表示只接收TCP/IP数据包。
过滤字符串的格式完全参照 WinPcap 用户手册,详细参数的定义和解释见下方链接:
Filtering expression syntax [WinPcap user’s manual]
在本教程中,展示了如何对协议类型、源IP地址和目的IP地址这三个参数进行过滤。如下方代码中高亮所示,在开始捕获之前设置Filter属性实现封包过滤,其中RcvPacketFilter 函数用于生产过滤字符串表达式。
在这里插入图片描述
RcvPacketFilter 函数负责对控件中输入的参数进行判断,然后生成规定格式的字符串,代码如下:

        /// <summary>/// 根据要求构造数据包过滤字符串/// </summary>private string RcvPacketFilter(){SnapProtocol proto = (SnapProtocol)comboBox2.SelectedIndex;IPAddress src_host, dst_host;string filter = proto.ToString();if ((textBox1.Text.Trim().Length > 0) && (IPAddress.TryParse(textBox1.Text, out src_host))){filter += string.Format(" and src host {0}", src_host.ToString());}if ((textBox2.Text.Trim().Length > 0) && (IPAddress.TryParse(textBox2.Text, out dst_host))){filter += string.Format(" and dst host {0}", dst_host.ToString());}return filter;}

表达式最终的格式为:
proto{ and src host xxx.xxx.xxx.xxx}{ and dst host xxx.xxx.xxx.xxx}
如果TextBox 控件中填入了IP地址,则对于源IP地址(src host)或者目的IP 地址(dst host)就作为过滤条件,例如:
udp and src host 192.168.1.100 and dst host 192.168.1.101
如果对应的IP地址为空,该项就被忽略。例如,源地址TextBox为空,则最终生成的字符串为:
udp and dst host 192.168.1.101
按照上述方式构造字符串即可实现过滤,其它过滤条件使用方式类似。

2.6 捕获数据包

在设置完成后,进入捕获状态后,如4.3.3节所述,捕获到满足条件的数据包以后,程序将调用被注册的事件函数 device_OnPacketArrival,通过该函数我们可以通过编写相关代码对捕获的数据包进行处理。
本实验展示了如何在 OnPacketArrival 中提取数据包的时间戳、长度、源IP 地址、目的IP地址以及协议类型。上述参数将伴随整个数据包内容以字符串的形式显示在RichTextBox中。函数定义如下:
在这里插入图片描述

        private void device_OnPacketArrival(object sender, CaptureEventArgs packet){// 时间和长度的获取DateTime time = packet.Packet.Timeval.Date;int len = packet.Packet.Data.Length;// 解析数据包成:IP包Packet p = Packet.ParsePacket(packet.Packet.LinkLayerType, packet.Packet.Data);IpPacket ip = (IpPacket)p.Extract(typeof(IpPacket));// 数据包信息string info = string.Format("\nsrc_addr={0}, des_addr={1}, type={2}\n",ip.SourceAddress, ip.DestinationAddress, ip.Protocol);info += string.Format("{0}:{1}:{2},{3} Len={4}\n",time.Hour, time.Minute, time.Second, time.Millisecond, len);info += string.Format(byteToHexStr(packet.Packet.Data));// 使用委托显示结果richTextBox1.Invoke(disp_info, info);}

在这一节中需要对以太网的帧格式有一定的了解,本试验中部分参数需要解析数据包的内容来获得。其中程序的时间和数据长度可以直接访问属性获得,而以太网帧内的IP地址信息则需要通过分析数据包内容得到。

SharpPcap 中提供了所有报文格式的解析方式,可以方便直观地解析以太网中所有的字段,如上述代码中高亮部分:

函数Packet.ParsePacket 用于将数据 packet.Packet.Data 解析成以太网帧;Extract 函数可以提取并解析以太网帧中的各种报文。进行提取和解析后,其中的组成部分就可以通过属性的形式获得。如上述代码中的灰色部分,IP 数据报的源IP地址、目的IP地址和协议类型通过属性的形式可以直接获得。 最后,将所有内容转换成字符串,提交给委托函数进行显示。

三、运行程序

在这里插入图片描述

四、结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关文章:

计算机网络实验课(二)——抓取网络数据包,并实现根据条件过滤抓取的以太网帧,分析帧结构

文章目录 一、添加控件二、代码分析2.1 代码2.2 控件初始化2.3 打开和关闭设备2.4 开始和结束捕获2.5 设置捕获条件2.6 捕获数据包 三、运行程序四、结果分析 提要&#xff1a;如果你通过vs打开.sln文件&#xff0c;然后代码界面或者前端界面都没找到&#xff0c;视图里面也没找…...

自动生成提示技术突破:AUTOPROMPT重塑语言模型应用

AUTOPROMPT 预训练语言模型的显著成功促使人们研究这些模型在预训练期间学习了哪些类型的知识。将任务重新表述为填空题(例如,完形填空测试)是衡量此类知识的自然方法 但是,它的使用受到编写合适提示所需的手动工作和猜测的限制。为了解决这个问题,我们开发了 AUTOPROMP…...

78. Subsets和90. Subsets II

目录 78.子集 方法一、迭代法实现子集枚举 方法二、递归法实现子集枚举 方法三、根据子集元素个数分情况收集 方法四、直接回溯法 90.子集二 方法一、迭代法实现子集枚举 方法二、递归法实现子集枚举 方法三、根据子集元素个数分情况收集 方法四、直接回溯法 78.子集…...

VSCode 插件 GitLens 破解方法

文章目录 1. 安装指定版本2. 修改插件文件3. 重启 VSCode 1. 安装指定版本 在 VSCode 中打开扩展&#xff08;Ctrl Shift X&#xff09;&#xff0c;搜索 GitLens&#xff0c;右键点击 安装特定版本&#xff0c;在弹出的窗口中选择 17.0.2&#xff0c;然后等待安装完成。 2…...

linux 通过命令将 MinIO 桶的权限设置为 Custom(自定义策略)

在 Ubuntu 下&#xff0c;如果要通过命令将 MinIO 桶的权限设置为 Custom&#xff08;自定义策略&#xff09;&#xff0c;可以使用 mc&#xff08;MinIO Client&#xff09;、AWS CLI 或直接调用 MinIO API&#xff08;如 curl&#xff09;。以下是几种方法&#xff1a; 方法 …...

模型评价指标介绍

模型评价指标介绍 **在机器学习与数据科学领域&#xff0c;构建模型仅是工作的一部分&#xff0c;更为关键的是要精准评估模型的性能。模型评价指标作为衡量模型表现的标准&#xff0c;有助于数据科学家、分析师等从业者判断模型的优劣&#xff0c;进而进行优化与改进。不同类…...

ElasticSearch整合SpringBoot

ElasticSearch 整合SpringBoot ES官方提供了各种不同语言的客户端。用来操作ES。这些客户端的本质就是组装DSL语句&#xff0c;通过HTTP请求发送给ES。 设计索引库 跟据数据库的表结构进行ES索引库的创建时。如果字段需要进行倒排索引的时候请为它指定分词器。如果该字段不是…...

ArcGIS Pro 3.4 二次开发 - 知识图谱

环境:ArcGIS Pro SDK 3.4 + .NET 8 文章目录 知识图谱1 知识图谱数据存储1.1 打开与知识图谱的连接1.2 从KnowledgeGraphLayer获取连接1.3 检索GDB要素类和定义1.4 检索GDB表和定义1.5 从知识图谱数据存储中获取服务 Uri1.6 将一组对象ID转换为实体的ID1.7 将一组ID转换为实体…...

2025上半年软考高级系统架构设计师经验分享

笔者背景 笔者在成都工作近7年&#xff0c; 一直担任研发大头兵&#xff0c;平日工作主要涵盖应用开发&#xff08;Java&#xff09;与数仓开发&#xff0c;对主流数据库、框架等均有涉猎&#xff0c;但谈不上精通。 最近有一些职业上的想法&#xff0c;了解到软考有那么一丁点…...

uni-app学习笔记十二-vue3中创建组件

通过组件&#xff0c;可以很方便地实现页面复用&#xff0c;减少重复页面的创建&#xff0c;减少重复代码。一个页面可以引入多个组件。下面介绍在HBuilder X中创建组件的方法&#xff1a; 一.组件的创建 1.选中项目&#xff0c;右键-->新建目录(文件夹)&#xff0c;并将文…...

React 虚拟dom

虚拟dom react核心机制 内存中轻量级JS对象树模拟真实DOM&#xff0c;主要目的是减少操作真实dom的开销 具体是通过diff算法计算最小的变更&#xff0c;批处理更新真实dom元素 diff算法 特点 同级去进行比较&#xff0c;不涉及跨层的一个比较 使用key值优化列表遍历过程 …...

互联网大厂Java求职面试:AI与大模型应用集成中的架构难题与解决方案-1

互联网大厂Java求职面试&#xff1a;AI与大模型应用集成中的架构难题与解决方案-1 场景描述 郑薪苦&#xff0c;一个看似不靠谱但技术潜力巨大的程序员&#xff0c;在一次针对AI与大模型应用集成的面试中&#xff0c;被一位技术总监级别的人物提问。面试官以严肃专业的态度&a…...

《算法笔记》13.2小节——专题扩展->树状数组(BIT) 问题 D: 数列-训练套题T10T3

数列(sequence.pas/c/cpp) - 问题描述 一个简单的数列问题&#xff1a;给定一个长度为n的数列&#xff0c;求这样的三个元素ai, aj, ak的个数&#xff0c;满足ai < aj > ak&#xff0c;且i < j < k。 - 输入数据 第一行是一个整数n(n < 50000)。 第二行n个整…...

一键启动多个 Chrome 实例并自动清理的 Bash 脚本分享!

目录 一、&#x1f4e6; 脚本功能概览 二、&#x1f4dc; 脚本代码一览 三、&#x1f50d; 脚本功能说明 &#xff08;一&#xff09;✅ 支持批量启动多个 Chrome 实例 &#xff08;二&#xff09;✅ 每个实例使用独立用户数据目录 &#xff08;三&#xff09;✅ 启动后自…...

4 月 62100 款 App 被谷歌下架!环比增长 28%

大家好&#xff0c;我是牢鹅&#xff01;上周刚刚结束的 2025 年 Google I/O 开发者大会&#xff0c; Google Play 带来了一系列的更新&#xff0c;主要围绕提升优质 App 的"发现"、"互动"和"收入"三大核心内容。 这或许正是谷歌生态的一个侧影…...

图像分割全路线学习(结合论文)

本篇文章参考自开源大佬的文章并结合自己的思考而来&#xff0c;欢迎大家提出意见&#xff0c;论文代码同样来自开源&#xff0c;文中已注明 文章目录 图像分割图像分割算法分类&#xff1f;传统的基于CNN的分割方法缺点&#xff1f;FCN详解FCN改变了什么?FCN网络结构&#x…...

Go语言之定义结构体(Struct)-《Go语言实战指南》

结构体&#xff08;struct&#xff09;是 Go 中的一种复合数据类型&#xff0c;它允许你将多个不同类型的字段组合成一个类型&#xff0c;类似于 C 语言的结构体或面向对象语言中的类。 一、结构体的基本定义 type 结构体名 struct {字段名 字段类型... } 示例&#xff1a; …...

mediapipe标注视频姿态关键点(基础版加进阶版)

前言 手语视频流的识别有两种大的分类&#xff0c;一种是直接将视频输入进网络&#xff0c;一种是识别了关键点之后再进入网络。所以这篇文章我就要来讲讲如何用mediapipe对手语视频进行关键点标注。 代码 需要直接使用代码的&#xff0c;我就放这里了。环境自己配置一下吧&…...

PCtoLCD2002如何制作6*8字符

如何不把“等比缩放”前的打勾取消&#xff0c;则无法修改为对应英文字符为6*8。 取消之后就可以更改了&#xff01;...

SmartPlayer与VLC播放RTMP:深度对比分析延迟、稳定性与功能

随着音视频直播技术的发展&#xff0c;RTMP&#xff08;实时消息传输协议&#xff09;成为了广泛应用于实时直播、在线教育、视频会议等领域的重要协议。为了确保优质的观看体验&#xff0c;RTMP播放器的选择至关重要。大牛直播SDK的SmartPlayer和VLC都是在行业中广受欢迎的播放…...

Qt QPaintEvent绘图事件painter使用指南

绘制需在paintEvent函数中实现 用图片形象理解 如果加了刷子再用笔就相当于用笔画过的区域用刷子走 防雷达&#xff1a; 源文件 #include "widget.h" #include "ui_widget.h" #include <QDebug> #include <QPainter> Widget::Widget(QWidget…...

伪创新-《软件方法》全流程引领AI-第1章 04

《软件方法》全流程引领AI-第1章 ABCD工作流-01 对PlantUML们的评价-《软件方法》全流程引领AI-第1章 02 AI辅助的建模步骤-《软件方法》全流程引领AI-第1章 03 第1章 ABCD工作流 1.5 警惕和揭秘伪创新 初中数学里要学习全等三角形、相似三角形、SSS、SAS……&#xff0c;到…...

win11如何重启

在 Windows 11 中重启电脑有多种方法&#xff0c;以下是其中几种常见方法&#xff1a; 开始菜单重启&#xff1a; 点击屏幕左下角的“开始”按钮&#xff08;Windows 图标&#xff09;。 在开始菜单中&#xff0c;点击“电源”图标。 选择“重启”选项。 使用快捷键&#xf…...

【iOS】 锁

iOS 锁 文章目录 iOS 锁前言线程安全锁互斥锁pthread_mutexsynchronized (互斥递归锁)synchronized问题:小结 NSLockNSRecursiveLockNSConditionNSConditionLock 自旋锁OSSpinLock(已弃用)atomicatomic修饰的属性绝对安全吗?os_unfair_lock 读写锁互斥锁和自旋锁的对比 小结使…...

uni-app学习笔记十五-vue3页面生命周期(一)

页面生命周期概览 vue3页面生命周期如下图所示&#xff1a; onLoad 此时页面还未显示&#xff0c;没有开始进入的转场动画&#xff0c;页面dom还不存在。 所以这里不能直接操作dom&#xff08;可以修改data&#xff0c;因为vue框架会等待dom准备后再更新界面&#xff09;&am…...

Flink核心概念小结

文章目录 前言引言数据流API基于POJO的数据流基本源流配置示例基本流接收器数据管道与ETL(提取、转换、加载)一对一映射构建面向流映射的构建键控流进行分组运算RichFlatMapFunction对于流的状态管理连接流的使用流式分析水位的基本概念和示例侧道输入的基本概念和示例Process …...

《软件工程》第 14 章 - 持续集成

在软件工程的开发流程中&#xff0c;持续集成是保障代码质量与开发效率的关键环节。本章将围绕持续集成的各个方面展开详细讲解&#xff0c;结合 Java 代码示例与可视化图表&#xff0c;帮助读者深入理解并实践相关知识。 14.1 持续集成概述 14.1.1 持续集成的相关概念 持续集…...

大模型 Agent 中的通用 MCP 机制详解

1. 引言 大模型(Large Language Model,LLM)技术的迅猛发展催生了一类全新的应用范式:LLM Agent(大模型 Agent)。简单来说,Agent 是基于大模型的自治智能体,它不仅能理解和生成自然语言,还能通过调用工具与环境交互,从而自主地完成复杂任务。ChatGPT 的出现让人们看到…...

Navicat 17 SQL 预览时表名异常右键表名,点击设计表->SQL预览->另存为的SQL预览时,表名都是 Untitled。

&#x1f9d1;‍&#x1f4bb; 用户 Navicat 17 SQL 预览时表名异常右键表名&#xff0c;点击设计表->SQL预览->另存为的SQL预览时&#xff0c;表名都是 Untitled。 &#x1f9d1;‍&#x1f527; 官方技术中心 了解到您的问题&#xff0c;这个显示是正常的&#xff0c…...

Orpheus-TTS:AI文本转语音,免费好用的TTS系统

名人说&#xff1a;博观而约取&#xff0c;厚积而薄发。——苏轼《稼说送张琥》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、Orpheus-TTS&#xff1a;重新定义语音合成的标准1. 什么是Orpheus-TTS&#xff…...