window环境下,如何通过USB接口控制打印机

虽然说大多数情况下,我们可以非常便利的通过打印机驱动来控制打印机,但还是有一些特殊情况,导致无法通过打印机驱动来完成我们预想的任务,比如,打印机只是一个系统设备中的一部分,需要协调其它设备一起工作时,如果只是通过打印机驱动来完成打印任务,就很难与系统中的其它设备完美协调。

那么,我们应该如何解决这种问题呢?一、开发特定的打印机驱动来配合;二、定制专用的Firmware,增加特殊的控制指令,通过USB端口来控制打印机的打印并实时获取打印机当前的工作状态,从而实现完美配合系统其它设备的功能。

那么,新的问题来了,我们应该选择方案一还是方案二呢?其实这个问题,不难选择,大多数情况下,有这种需求的打印机,就不是一款通用形的打印机,而是一款定制的或专用于某个领域的打印机,也就意味着,这种打印机本就是定制的,从硬件到Firmware,都是定制的,所以,显然选择方案二是最合适的。

新问题又有了,我们如何才能通过USB端口控制打印机呢?回答这个问题之前,我们先介绍一下window系统下usb设备的类型。

一、usb设备的类型

USB设备类型根据功能和应用场景可分为以下几大类:

一)、常用设备类

  1. HID(人机接口设备)

    • 用途:用于人与计算机交互的输入设备
    • 示例:键盘、鼠标、游戏手柄
    • 协议特征:支持低速/全速模式,兼容性强
  2. MSC(大容量存储设备)

    • 用途:数据传输与存储
    • 示例:U盘、移动硬盘、SD卡读卡器
    • 协议速度:USB 2.0最高支持480Mbps
  3. CDC(通信设备类)

    • 用途:串行通信与网络连接
    • 示例:调制解调器、网络摄像头
    • 应用场景:虚拟COM端口、数据透传
  4. Audio Class(音频设备类)

    • 用途:音频输入/输出
    • 示例:USB麦克风、耳机、MIDI设备
    • 应用特点:支持音频流传输与处理
  5. Video Class(视频设备类,UVC)

    • 用途:视频捕捉与传输
    • 示例:网络摄像头、视频采集卡
    • 协议优势:标准化视频传输协议

二)、其他设备类

  1. Printer Class(打印机类)
    • 用途:打印机控制与数据传输
  2. PTP(图像传输协议)
    • 用途:相机、扫描仪等图像设备的数据传输
  3. Hub Class(集线器类)
    • 用途:扩展USB端口数量

三)、物理接口类型

虽然与功能分类无关,但物理接口类型影响设备兼容性:

  • Type-A‌:最常见接口,用于U盘、键盘等
  • Type-C‌:正反插设计,支持高速数据传输与供电
  • Micro/Mini USB‌:主要用于旧款手机及小型设备

注:USB设备类与物理接口类型无直接绑定关系,同一接口(如Type-C)可能支持多种设备类功能

二、USB 设备 GUID 核心解析

一)、GUID 的定义与作用

GUID(全局唯一标识符)‌ 是用于标识 USB 设备类别的 128 位唯一编码,确保不同设备接口或功能在系统中被精准识别。

  • 设备接口类 GUID‌:标识设备的具体功能接口(如打印机、存储设备),
    例如 USB 打印设备的接口 GUID 为
     GUID_DEVINTERFACE_USBPRINT{28d78fad-5a12-11d1-ae5b-0000f803a8c2}
  • 设备安装类 GUID‌:用于管理驱动安装分类(如鼠标、键盘),通过注册表路径 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class 查看对应关系。

二)、GUID 与硬件标识符的关系

标识符含义用途
VID供应商 ID(由 USB-IF 分配)标识设备制造商
PID产品 ID(由厂商自定义)区分同一厂商的不同产品型号
GUID全局唯一标识符(系统或驱动定义)系统层面管理设备接口或驱动分类(如 GUID_DEVINTERFACE_USBPRINT 标识打印接口)

三)、系统级 GUID 应用场景

  1. 驱动匹配与加载

    • Windows 系统通过设备接口类 GUID 自动加载对应驱动程序(如 usbprint.sys 驱动绑定 GUID_DEVINTERFACE_USBPRINT)。
    • 若 GUID 与驱动注册不匹配,设备管理器会显示未知设备或错误代码(如 43)。
  2. 设备枚举与管理

    • 使用 API SetupDiGetClassDevs 时需指定 GUID 来筛选设备(示例:DIGCF_DEVICEINTERFACE | DIGCF_PRESENT 枚举已连接的 USB 打印机)。
    • 设备路径(如 \\?\USB#VID_xxxx&PID_xxxx#...)中隐含 GUID 信息,用于底层通信。

四)、GUID 查看与调试方法

  1. 注册表查看

    • 设备接口类 GUID‌:通过 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses 分支查询。
    • 设备安装类 GUID‌:在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class 下按设备类别检索。
  2. 设备管理器调试

    • 右键设备 → ‌属性‌ → ‌详细信息‌ → 选择 ‌设备类 GUID‌ 字段,查看当前设备绑定的 GUID。

五)、Windows 11 的 GUID 管理优化

  • 动态切换机制‌:针对多功能设备(如打印扫描一体机),系统会根据当前操作模式动态切换 GUID,优化资源分配。
  • USB4 兼容性增强‌:新增 USB4 设备接口 GUID(如隧道协议支持),提升高速数据传输和 DisplayPort 视频流的稳定性

 三、USB 打印设备 GUID

一)、USB 打印设备接口 GUID

Windows 系统通过 ‌GUID(全局唯一标识符)‌ 识别特定设备类型。对于 USB 打印机,其设备接口 GUID 定义为:

DEFINE_GUID(GUID_DEVINTERFACE_USBPRINT, 0x28d78fad, 0x5a12, 0x11d1, 0xae, 0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2);

该 GUID 用于通过 Windows API 枚举和识别 USB 打印设备。

二)、获取 GUID 的编程方法

  1. 设备枚举核心代码
     

    #include <SetupAPI.h>
    #include <initguid.h>
    #include <Usbiodef.h>HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBPRINT,  // 指定打印机接口 GUIDNULL,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
    );
    

    通过 SetupDiGetClassDevs 函数可获取所有已连接的 USB 打印机设备实例。

  2. 设备路径提取

    SP_DEVICE_INTERFACE_DATA interfaceData = {0};
    interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);// 遍历设备接口列表
    SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_USBPRINT, 0, &interfaceData);
    
    结合 SetupDiGetDeviceInterfaceDetail 可进一步获取设备物理路径(如 \\?\USB#VID_04B8&PID_0202...)

四、实例说明通过USB端口控制打印机

 一)、枚举USB打印机端口

DEFINE_GUID(GUID_DEVINTERFACE_USBPRINT,0x28d78fad, 0x5a12, 0x11d1, 0xae, 0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2);#define	FX_PRINTER_ID	_T("\\\\?\\USB#VID_03EB&PID_6013#")
#define	SL_PRINTER_ID	_T("\\\\?\\USB#VID_03EB&PID_6006#")
#define	ST_PRINTER_ID	_T("\\\\?\\USB#VID_03EB&PID_5008#")
#define OEM_PRINTER_ID	_T("\\\\?\\USB#VID_0009&PID_0005#")BYTE	CUSB_Device::EnumDeviceInterface(CString * pszDevicePath, CString * pszDeviceID, int nports)
{int           MemberIndex = 0;LONG          Result = 0;DWORD         Length = 0;HANDLE        hDevInfo;ULONG         Required;BYTE	index = 0;PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;SP_DEVICE_INTERFACE_DATA  devInfoData;hDevInfo = SetupDiGetClassDevs((LPGUID)&(GUID_DEVINTERFACE_USBPRINT), NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);if (hDevInfo == INVALID_HANDLE_VALUE){
//		MessageBox(NULL, _T("No hardware device"), NULL, MB_OK);return 0;}devInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);//Step through the available devices looking for the one we want. do{Result = SetupDiEnumDeviceInterfaces(hDevInfo, 0, (LPGUID)&(GUID_DEVINTERFACE_USBPRINT), MemberIndex++, &devInfoData);if (Result != 0){SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, NULL, 0, &Length, NULL);//Allocate memory for the hDevInfo structure, using the returned Length.//			detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)new BYTE[Length * 4];detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(GPTR, Length);;if (detailData != NULL){//Set cbSize in the detailData structure.              detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);//Call the function again, this time passing it the returned buffer size.if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, detailData, Length, &Required, NULL) == TRUE){CString szID(detailData->DevicePath);szID.MakeUpper();if ((szID.Find(SL_PRINTER_ID, 0) != -1) || (szID.Find(ST_PRINTER_ID, 0) != -1) || (szID.Find(FX_PRINTER_ID, 0) != -1) || (szID.Find(OEM_PRINTER_ID, 0) != -1)){if (nports != 0){if (index < nports){if (pszDevicePath != NULL)pszDevicePath[index] = szID;if (pszDeviceID != NULL){int iPID_POS = szID.Find(_T("PID_"));m_szSerial = szID.Right(szID.GetLength() - iPID_POS - 9);int iret = m_szSerial.Find(_T("#"));m_szSerial = m_szSerial.Left(iret);pszDeviceID[index] = m_szSerial;}index++;}}else{index++;}}}GlobalFree(detailData);}}} while (Result != 0 && MemberIndex < 127);SetupDiDestroyDeviceInfoList(hDevInfo);if (!Result && (MemberIndex >= 127)){
//		MessageBox(NULL, _T("Can not Open USB port"), NULL, MB_OK);return 0;}return index ;
}

系统有可能连接多台打印机,所以我们只要枚举需要控制的打印机端口,下面代码就是用来判断是否是我们需要控制的打印机端口。

if ((szID.Find(SL_PRINTER_ID, 0) != -1) || (szID.Find(ST_PRINTER_ID, 0) != -1) || (szID.Find(FX_PRINTER_ID, 0) != -1) || (szID.Find(OEM_PRINTER_ID, 0) != -1))

 下面代码用于打开USB打印端口:

						m_hDevice = CreateFile(detailData->DevicePath,GENERIC_READ | GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);

二)、写USB打印端口

DWORD CUSB_Device::writePort(BYTE *buff, DWORD len)
{DWORD writtedLen,idx,waitTimes,n,tempLen;BOOL bResult;ASSERT(buff);if( !(buff && len && this->openPort()))return 0;writtedLen = 0;idx = 0;waitTimes = 0;m_percent = 0;tempLen = len;OVERLAPPED overlapped;memset(&overlapped,0,sizeof(OVERLAPPED));overlapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);while(len){n = tempLen - idx;if( n > _SEND_BLOCK_SIZE)n = _SEND_BLOCK_SIZE;if (!::WriteFile(m_hDevice, &buff[idx], n, &writtedLen, &overlapped)){if (GetLastError() == ERROR_IO_PENDING)//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行操作{//使用WaitForSingleObject函数等待,直到读操作完成或延时已达到1秒钟//当串口操作进行完毕后,overlapped的hEvent事件会变为有信号while(WaitForSingleObject(overlapped.hEvent,2000) != WAIT_OBJECT_0){waitTimes++;if(waitTimes > 6){BYTE	lpstatus[_MAX_USB_RECEIVED];if (GetPrinterStatus(lpstatus) > 0){if ((lpstatus[0] & 0xff) == 0x98){MessageBox(NULL, NULL, _TEXT("读写USB口出错!"), MB_OK | MB_ICONINFORMATION );return	idx;}}}}waitTimes = 0;bResult = GetOverlappedResult(m_hDevice, &overlapped, &writtedLen, FALSE);if (!bResult) break; }else{if(waitTimes > 1)break;waitTimes++;writtedLen = 0;m_hDevice = INVALID_HANDLE_VALUE;this->openPort();}}idx += writtedLen;len -= writtedLen;m_percent = (BYTE)(idx * 100 / tempLen);}return idx;
}

三)、读打印端口

DWORD CUSB_Device::readPort(BYTE *buff, DWORD len)
{DWORD readLen,dataLen,waitTimes = 0;
//	BOOL bResult;BYTE *lpBuff;ASSERT(buff);if( !(buff && len && this->openPort()))return 0;OVERLAPPED overlapped;memset(&overlapped,0,sizeof(OVERLAPPED));overlapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//	bResult = TRUE;readLen = 0;dataLen = 0;lpBuff = buff;while(true){::ReadFile(m_hDevice, lpBuff, len, &readLen, &overlapped);if (GetLastError() == ERROR_IO_PENDING)//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行操作{//使用WaitForSingleObject函数等待,直到读操作完成或延时已达到1秒钟//当串口操作进行完毕后,overlapped的hEvent事件会变为有信号
#if	1BOOL	timewait=TRUE;while(timewait){switch(WaitForSingleObject(overlapped.hEvent,6000)){case WAIT_OBJECT_0:timewait = FALSE;break;case WAIT_TIMEOUT:case WAIT_ABANDONED:default:return 0;}}
//			GetOverlappedResult(m_hDevice, &m_ReadOvlp, &curLen, TRUE);
#elsewhile(WaitForSingleObject(overlapped.hEvent,2000) != WAIT_OBJECT_0){waitTimes++;if(waitTimes > 6){::CloseHandle(overlapped.hEvent);break;}}
#endifwhile (!GetOverlappedResult(m_hDevice, &overlapped, &readLen, FALSE));
//			if (!bResult) 
//				break;dataLen += readLen;if(dataLen < len){lpBuff += readLen;len -= readLen;continue;}elsebreak;}else{if(waitTimes > 1)break;waitTimes++;m_hDevice = INVALID_HANDLE_VALUE;this->openPort();}}	if(dataLen != len)return 0;return dataLen;
}

 四)、获取打印机状态

BOOL Control_Info(HANDLE hDevice,DWORD cntrlCode,LPTSTR buff,DWORD &len)
{BOOL	retFlag;DWORD	retLen;retFlag = DeviceIoControl(hDevice,		//HANDLE hDevice,cntrlCode,//DWORD cntrlCode,NULL,			//LPVOID lpInBuffer,0,				//DWORD nInBufferSize,buff,			//LPVOID lpOutBuffer,len,			//DWORD nOutBufferSize,&retLen,			//LPDWORD lpBytesReturned,NULL			// LPOVERLAPPED lpOverlapped);len = retLen;return retFlag;
}BYTE	CUSB_Device::GetPrinterStatus(BYTE * lpsts)
{
//	return 1;DWORD	len = _MAX_USB_RECEIVED;TCHAR	lptemp[_MAX_USB_RECEIVED];if( !(this->openPort()))return 0;if (Control_Info(m_hDevice,IOCTL_USBPRINT_GET_LPT_STATUS,lptemp,len)){*lpsts = (BYTE)lptemp[0];return (BYTE)len;}elsereturn 0;
}

本来想上传完整源代码的,但不知道为什么,一直显示上传中断,无法上传,有需要的朋友可以联系我。

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

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

相关文章

CDGP数据治理主观题评分标准与得分策略

1.数据模型题目评分标准 1)准确理解题目中所描述的业务逻辑和需求得[1分] 2)正确使用模型设计方法,使用信息工程、信息建模集成定义、巴克符号、陈氏符号等其中一种得[1分] 3)正确设计实体和属性,题目中涉及的实体数量为25-30个,10个以内得[2分],10-20个得[3分],25个…

工业设计破局密码:3D 可视化技术点燃产业升级引擎

3D可视化是一种将数据、信息或抽象概念以三维图形、模型和动画的形式呈现出来的技术。3D可视化技术通过构建三维数字孪生体&#xff0c;将设计思维转化为可交互的虚拟原型&#xff0c;不仅打破了传统二维设计的空间局限&#xff0c;更在效率、精度与用户体验层面开创了全新维度…

Qt中在子线程中刷新UI的方法

Qt中在子线程中刷新UI的方法 在Qt中UI界面并不是线程安全的&#xff0c;意味着在子线程中不能随意操作UI界面组件&#xff08;比如按钮、标签&#xff09;等&#xff0c;如果强行操作这些组件有可能会导致程序崩溃。那么在Qt中如何在子线程中刷新UI控件呢&#xff1f; 两种方…

为了摸鱼和吃瓜,我开发了一个网站

平时上班真的比较累&#xff0c;摸鱼和吃瓜还要跳转多个平台的话&#xff0c;就累上加累了。 所以做了一个聚合了全网主流平台热搜的网站。 目前市面上确实有很多这种网站了&#xff0c;所以目前最主要有两点和他们不同&#xff1a; 给热搜列表增加了配图&#xff0c;刷的时候…

操作系统学习笔记第2章 (竟成)

第 2 章 进程管理 【考纲内容】 1.进程与线程&#xff1a; (1) 进程 / 线程的基本概念&#xff1b; (2) 进程 / 线程的状态与转换&#xff1b; (3) 线程的实现&#xff1a;内核支持的线程&#xff1b;线程库支持的线程&#xff1b; (4) 进程与线程的组织与控制&#xff1b; (5)…

77.评论日记

房间要经常搞卫生&#xff0c;不然会很多灰&#xff0c;很多头发&#xff0c;很多垃圾。 当然&#xff0c;即使一直搞卫生&#xff0c;在一些看不到的角落也是会慢慢囤积垃圾。 想要把那些角落也打扫干净&#xff0c;没别的办法&#xff0c;只有把那个角落上所有的东西都移开&a…

语音合成之十二 TTS声学编解码器的演进

TTS声学编解码器的演进 1 引言&#xff1a;声码器/声学编解码器在现代TTS中的关键作用2 奠定基石&#xff1a;从早期声码器到神经合成的曙光3. HiFi-GAN: 革新高效高保真波形生成4. 新的疆域&#xff1a;面向富语义TTS的先进声学编解码器5. XCodec2.0: 统一声学与语义信息6.BiC…

大学之大:悉尼科技大学2025.5.10

悉尼科技大学&#xff1a;从技术先驱到全球创新枢纽的百年征程 一、历史沿革&#xff1a;从技工培训到世界百强名校的蜕变 1. 工业革命的技术火种&#xff08;1843-1945&#xff09; 悉尼科技大学的历史可追溯至1843年成立的悉尼机械学院&#xff08;Sydney Mechanics’ Scho…

安装阿里云的yum源并且下载软件(CentOS7版本)

目录 1. 进入root模式: 2. 进入yum.repos.d文件下 3.备份 4. 安装阿里云的yum源 5. 安装dnf 6. 安装epel-release 7. 清除缓存,并新建缓存 8. 安装智能拼音软件包 8.1安装 8.2 进入应用程序 -- 系统工具 -- 设置 8.3重启后就可以打中文啦~ (需要重新启动才能)…

Discriminative and domain invariant subspace alignment for visual tasks

用于视觉任务的判别性和域不变子空间对齐 作者&#xff1a;Samaneh Rezaei&#xff0c;Jafar Tahmoresnezhad 文章于2018年12月4日收到&#xff0c;2019年5月24日被接受&#xff0c;2019年6月3日在线发表于Iran Journal of Computer Science期刊&#xff0c;DOI: 10.1007/s42…

用jsp简单实现C语言标准化测试系统

C语言标准化测试系统 在Web编程技术的学习过程中&#xff0c;我们小组为了深入理解相关技术原理&#xff0c;提升实践能力&#xff0c;开发了一个基于动态Web工程框架的C语言标准化考试系统。现在&#xff0c;就来和大家分享一下我们的项目经历。 一、实验目的剖析 这个项目…

QMK键盘固件自定义指南 - 打造你的专属键盘体验

QMK键盘固件自定义指南 - 打造你的专属键盘体验 &#x1f680; 前言 在机械键盘的世界里&#xff0c;QMK固件让你的键盘不再只是简单的输入设备&#xff0c;而是可以按照你的意愿定制的强大工具。本文将深入浅出地介绍如何自定义QMK键盘的行为&#xff0c;从基础概念到高级应…

5.9培训

文件上传 先找文件上传的地方&#xff0c;打开代理链接BP&#xff0c;它需要一个xls文件 我们创建一个sqzr.xls bp拦截了之后&#xff0c;我们修改请求&#xff0c;把后缀改成php&#xff0c;发送请求 找到我们的静态资源所在的位置 访问http://192.168.1.100:81/static/upload…

【FAQ】HarmonyOS SDK 闭源开放能力 — PDF Kit

1.问题描述&#xff1a; 预览PDF文件&#xff0c;文档上所描述的loadDocument接口&#xff0c;可以返回文件的状态&#xff0c;并无法实现PDF的预览&#xff0c;是否有能预览PDF相关接口&#xff1f; 解决方案&#xff1a; 1、执行loadDocument进行加载PDF文件后&#xff0c…

AutoDL实现端口映射与远程连接AutoDL与Pycharm上传文件到远程服务器(李沐老师的环境)

文章目录 以上配置的作用前提AutoDL实现端口映射远程连接AutoDLPycharm上传文件到远程服务器以上配置的作用 使用AutoDL的实例:因本地没有足够强的算力,所以需要使用AutoDL AutoDL端口映射:当在实例上安装深度学习的环境,但因为实例的linux系统问题,无法图形化显示d2l中的文件…

【Linux系列】跨平台安装与配置 Vim 文本编辑器

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

CountDownLatch 并发编程中的同步利器

CountDownLatch 并发编程中的同步利器 文章目录 CountDownLatch 并发编程中的同步利器一、CountDownLatch 基础概念1.1 什么是 CountDownLatch&#xff1f;1.2 CountDownLatch 的核心方法1.3 基本使用示例 二、CountDownLatch 实战应用2.1 应用场景一&#xff1a;并行任务协调2…

Linux 内核链表宏的详细解释

&#x1f527; Linux 内核链表结构概览 Linux 内核中的链表结构定义在头文件 <linux/list.h> 中。核心结构是&#xff1a; struct list_head {struct list_head *next, *prev; }; 它表示一个双向循环链表的节点。链表的所有操作都围绕这个结构体展开。 &#x1f9e9; …

分书问题的递归枚举算法

分数问题的递归枚举算法 一、问题引入二、解题步骤1.问题分析思维导图2.解题步骤 三、代码实现1.代码2.复杂度分析 四、个人总结 一、问题引入 分书问题是指&#xff1a;已知 n 个人对 m 本书的喜好&#xff08;n≤m&#xff09;&#xff0c;现要将 m 本书分给 n 个人&#xf…

密码学--AES

一、实验目的 1、完成AES算法中1轮加密和解密操作 2、掌握AES的4个基本处理步骤 3、理解对称加密算法的“对称”思想 二、实验内容 1、题目内容描述 &#xff08;1&#xff09;利用C语言实现字节代换和逆向字节代换&#xff0c;字节查S盒代换 &#xff08;2&#xff09;利…