孙鑫VC学习笔记:第十七讲 (二) 用匿名管道实现进程间的通信

命名管道学习(简单例程)----Windows进程间通信 管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。通常我们把管道分为匿名管道和命名管道。但对于匿名管道的话,只能在本机上进程之间通信,而且只能实现本地的父子进程之间的通信,局限性太大了。而这里介绍的命名管道,就和匿名管道有些不同了,在功能上也就显得强大许多,至少其可以实现跨网络之间的进程的通信,同时其客户端既可以接收数据也可以发送数... 阅读详情
用匿名管道实现进程间的通信:
 
匿名管道只能在本地主机上,父子进程之间完成通信:
 
步骤:
1.新建一个项目Parent
2.增加“匿名管道”子菜单以及“创建管道”、“读取数据”与“写入数据”三个菜单项。
3.在CParentView 中添加两个成员句柄:
HANDLE m_hWrite;
HANDLE m_hRead;
4.为“创建管道”菜单项实现创建管道的功能
 
代码如下:
注:
          关闭进程和线程对象的句柄
CloseHandle (pi.hProcess); //关闭所返回的子进程句柄
CloseHandle (pi.hThread); //关闭子进程中主线程句柄
在创建新进程时,系统会建立一个主进程内核对象和一个线程内核对象,内核对象都有使用计数,
系统为内核对象赋初始的使用计数1,当CreateProgress在内部打开内核对象时,
每个对象的使用计数变为2,我们在父进程中如果不需要使用这两个句柄,
调用CloseHandle 关闭这两个句柄,
系统会将子进程的进程内核对象和线程内核对象减1,
当子进程中止运行时,系统会再将使用计数减一,此时内核对象实用计数为零,
进程内核对象和线程内核对象才能够被释放。
我们应该在不需要使用内核对象句柄的时候使用CloseHandle关闭句柄。
 
将结构体中所有成员置为零可以使用函数:
void ZeroMemory(PVOID Destination,SIZE_T Length);
 
要获得标准输入输出或标准错误句柄,使用函数:
HANDLE GetStdHandle(DWORD nStdHandle);
 
---------------------------------------------------------------------------------
5.接下来完成读取与写入数据的功能了
 
“读取数据”菜单项
“写入数据”菜单项
注.
在父进程创建管道,返回管道的读写句柄,调用CreateProcess启动子进程,
通过将子进程的标准输入输出句柄设置为管道的读写句柄,
相当于对管道的读写句柄做上标记然后传递给子进程。
在子进程中得到自己的标准输入输出句柄,相当于得到了管道的读写句柄。
     
匿名管道只能在父子进程间进行通信,因为匿名管道没有名字,
所以我们只有在调用CreateProcess时将管道的读写句柄传递给子进程。
 
---------------------------------------------------------------------------------
下面编写子线程程序:
 
1.新建一个项目Child添加到当前工作区
2.增加“匿名管道”子菜单以及“读取数据”与“写入数据”两个菜单项。
3.增加一个虚函数:CChildView::OnInitialUpdate(),
 
   首先在CChildView中添加两个成员句柄:
HANDLE m_hWrite;
HANDLE m_hRead;
   然后在CChildView::OnInitialUpdate()函数中得到标准输入输出句柄
m_hRead =   GetStdHandle(STD_INPUT_HANDLE);
m_hWrite = GetStdHandle(STD_OUTPUT_HANDLE);
 
4.接下来完成读取与写入数据的功能了
读取代码与前面父进程的代码完全一样
写入代码只改了一个字符串
---------------------------------------------------------------------------------
至此,我们的程序完成了。
值得注意的是,
子进程必须由父进程打开(点击“匿名管道”菜单的“创建管道”项),它才与父进程有父子关系。
如果先打开子进程,再打开父进程,那么这两个进程并无任何关系。
 
---------------------------------------------------------------------------------
创建管道相关函数说明:
---------------------------------------------------------------------------------
CreatePipe
创建一个命名管道,返回一个管道的读写句柄。
The CreatePipe function creates an anonymous pipe, and returns handles to the read and write ends of the pipe.
BOOL CreatePipe(
PHANDLE
 hReadPipe, // pointer to read handle 用来接收管道的读取句柄
PHANDLE hWritePipe, // pointer to write handle用来接收管道的写入句柄
LPSECURITY_ATTRIBUTES lpPipeAttributes, // pointer to security attributes
DWORD nSize // 指定管道缓冲区大小
);
参数3:lpPipeAttributes用来检测返回的句柄是否可以被子进程继承。
这里不能设置为NULL,因为管道只能在父子进程间通信,
子进程要获得父进程的管道句柄只能通过继承得到。
 
---------------------------------------------------------------------------------
启动进程:
CreateProcess
The CreateProcess function creates a new process and its primary thread. The new process executes the specified executable file.
BOOL CreateProcess(
LPCTSTR
 lpApplicationName, // 
LPTSTR lpCommandLine, // pointer to command line string传递命令行参数
LPSECURITY_ATTRIBUTES lpProcessAttributes, // process security attributes
LPSECURITY_ATTRIBUTES lpThreadAttributes, // thread security attributes
BOOL bInheritHandles, // handle inheritance flag
DWORD dwCreationFlags, //用来指定控制优先级类和进程创建的附加标记
LPVOID lpEnvironment, // pointer to new environment block
LPCTSTR lpCurrentDirectory, //指向完整路径的字符指针,指定子进程当前的驱动器和目录
LPSTARTUPINFO lpStartupInfo, // pointer to STARTUPINFO指定新进程主窗口如何出现
LPPROCESS_INFORMATION lpProcessInformation
// pointer to PROCESS_INFORMATION,用来接收关于新的进程的标识信息。

);
Parameters
lpApplicationName
Pointer to a null-terminated string that specifies the module to execute.
用来指定一个可执行模块的名字。也就是可以用来设定一个可执行程序的名字
The string can specify the full path and filename of the module to execute or it can specify a partial name.
这个字符串可以指定可执行文件的完整+文件名或者指定部分名字。
In the case of a partial name, the function uses the current drive and current directory to complete the specification.
如果指定部分名字,则应用程序在当前的驱动器、当前的目录下面搜索它,如果搜索失败也不会使用搜索路径。注意:指定名字时要指定扩展名。
The lpApplicationName parameter can be NULL. In that case, the module name must be the first white space-delimited token in the lpCommandLine string.
该参数可以为NULL,这时文件的名称由第二个参数lpCommandLine中的第一个空格以前的字符指定。
 If you are using a long filename that contains a space, use quoted strings to indicate where the filename ends and the arguments begin, otherwise, the filename is ambiguous.
lpCommandLine
Pointer to a null-terminated string that specifies the command line to execute. The system adds a null character to the command line, trimming the string if necessary, to indicate which file was actually used.
The lpCommandLine parameter can be NULL. In that case, the function uses the string pointed to bylpApplicationName as the command line.
If both lpApplicationName and lpCommandLine are non-NULL, *lpApplicationName specifies the module to execute, and *lpCommandLine specifies the command line. The new process can useGetCommandLine to retrieve the entire command line. C runtime processes can use the argc andargv arguments.
如果第一个参数为NULL,也就是用第二个参数来指定文件名,那么这人参数的第一个空格以前的字符会被认为是文件的名字,如果是长文件字,需要用引号把它括起来;如果没有加扩展名,则会自动加上.exe的扩展名;如果没有写全路径,则会按下下面6个路径进行搜索。
If lpApplicationName is NULL, the first white space-delimited token of the command line specifies the module name. If you are using a long filename that contains a space, use quoted strings to indicate where the filename ends and the arguments begin (see the explanation for the lpApplicationNameparameter). If the filename does not contain an extension, .EXE is assumed. If the filename ends in a period (.) with no extension, or the filename contains a path, .EXE is not appended. If the filename does not contain a directory path, the system searches for the executable file in the following sequence:
  1. The directory from which the application loaded.
  2. The current directory for the parent process.
  3. Windows 95 and Windows 98: The Windows system directory. Use theGetSystemDirectory function to get the path of this directory. 
    Windows NT: The 32-bit Windows system directory. Use theGetSystemDirectory function to get the path of this directory. The name of this directory is SYSTEM32.
  4. Windows NT: The 16-bit Windows system directory. There is no Win32 function that obtains the path of this directory, but it is searched. The name of this directory is SYSTEM.
  5. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
  6. The directories that are listed in the PATH environment variable.
If the process to be created is an MS-DOS - based or 16-bit Windows-based application,lpCommandLine should be a full command line in which the first element is the application name. Because this also works well for Win32-based applications, it is the most robust way to setlpCommandLine.
lpProcessAttributes
Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpProcessAttributes is NULL, the handle cannot be inherited.
 用来设定新进程的安全性,以及指定父进程以后生成的子进程是否具有这个对象的句柄。
Windows NT: The lpSecurityDescriptor member of the structure specifies a security descriptor for the new process. If lpProcessAttributes is NULL, the process gets a default security descriptor.
lpThreadAttributes
Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpThreadAttributes is NULL, the handle cannot be inherited.
用来设定新线程的安全性,以及指定父进程以后生成的子进程是否具有这个对象的句柄。
Windows NT: The lpSecurityDescriptor member of the structure specifies a security descriptor for the main thread. If lpThreadAttributes is NULL, the thread gets a default security descriptor.
bInheritHandles
Indicates whether the new process inherits handles from the calling process. 指定新的进程是否可以从调用进程继承句柄。
If TRUE, each inheritable open handle in the calling process is inherited by the new process. Inherited handles have the same value and access privileges as the original handles.
如果为真,则任何可继承的打开句柄都可以被新的进程所继承,
继承的句柄和原始句柄拥有同样的值和访问特权。
Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
 
---------------------------------------------------------------------------------
其中STARTUPINFO结构体定义如下:
STARTUPINFO
The STARTUPINFO structure is used with the CreateProcess function to specify main window properties if a new window is created for the new process. For graphical user interface (GUI) processes, this information affects the first window created by the CreateWindow function and shown by the ShowWindow function. For console processes, this information affects the console window if a new console is created for the process. A process can use theGetStartupInfo function to retrieve the STARTUPINFO structure specified when the process was created.
typedef struct _STARTUPINFO { // si
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
 } STARTUPINFO, *LPSTARTUPINFO;
Members
cb      指示结构体的大小,以字节为单位。
Specifies the size, in bytes, of the structure.
dwFlags
This is a bit field that determines whether certain STARTUPINFO members are used when the process creates a window. Any combination of the following values can be specified:
Value
STARTF_USESHOWWINDOW
STARTF_USEPOSITION
STARTF_USESIZE
STARTF_USECOUNTCHARS
这个值没有被指定,则dwXCountChars
与dwYCountChars成员被忽略。
STARTF_USEFILLATTRIBUTE
STARTF_FORCEONFEEDBACK
STARTF_FORCEOFFFEEDBACK
STARTF_USESTDHANDLES
用来设定我们所创建的进程的标准输入、标准输出和标准错误句柄。
The CreateProcess function's fInheritHandles parameter must be set to TRUE for this to work properly.
---------------------------------------------------------------------------------
PROCESS_INFORMATION
The PROCESS_INFORMATION structure is filled in by the CreateProcess function with information about a newly created process and its primary thread.
typedef struct _PROCESS_INFORMATION { // pi HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; } PROCESS_INFORMATION;
Members
hProcess
Returns a handle to the newly created process. The handle is used to specify the process in all functions that perform operations on the process object.
hThread
Returns a handle to the primary thread of the newly created process. The handle is used to specify the thread in all functions that perform operations on the thread object.
dwProcessId
Returns a global process identifier (全局进程标识符)that can be used to identify a process. The value is valid from the time the process is created until the time the process is terminated.
dwThreadId
Returns a global thread identifiers (全局线程标识符)that can be used to identify a thread. The value is valid from the time the thread is created until the time the thread is terminated.
 
---------------------------------------------------------------------------------
 
GetStdHandle
The GetStdHandle function returns a handle for the standard input, standard output, or standard error device.
HANDLE GetStdHandle(
DWORD
 nStdHandle // input, output, or error device
);
Parameters
nStdHandle
Specifies the device for which to return the handle. This parameter can have one of the following values:
Value Meaning
STD_INPUT_HANDLE
Standard input handle
STD_OUTPUT_HANDLE
Standard output handle
STD_ERROR_HANDLE
Standard error handle
 
MFC实现匿名管道通信(附完整源码) 阅读详情

相关推荐

进程间通信的VC++源码实例集,邮槽、匿名管道等

进程间通信的VC++源码实例集,进程之间的通信以及实现方法实例,通过一些小程序来实现,这些小程序有剪贴板实例、邮槽、匿名管道等,希望对VC++基础用户有帮助。

VC 进程间用匿名管道通信

1、注:在父进程中关闭不需要的句柄。 为什么需要关闭不用的句柄? 内核对象引用计数,是指系统内部有多少句柄在标识这内核对象(线程内核对象,进程内核对象). 创建一个新的进程的时候,系统会创建一个进程内核对象,和一个线程内核对象, 每一个内核对象都有一个使用计数,系统会为这两个对象赋予一个初始的计数一,在 CreateProcess返回之前,打开进程和线程对象, 并将和对象相关的句柄放入pi.hP...

ninioq的专栏 519

vc 进程通信(剪贴板 命名管道 匿名管道 邮槽)

vc 实现了4种进程间的通信,包括剪贴板 命名管道 匿名管道 邮槽

VC网络编程笔记--进程间通信-匿名管道

VC网络编程笔记--进程间通信-匿名管道

知行合一 566

VC++ 匿名管道读取写入与创建管道的实例

摘要:VC/C++源码,系统相关,匿名管道  VC++ 匿名管道相关的测试小程序,这个测试小程序演示了如何读娶写入与创建管道实例,源码运行截图如上所示,直接用VC++编译即可生成测试程序。

2025小红书跳转卡片实战指南:从零搭建独立后台与自动化发卡系统

本文提供了一份2025年小红书跳转卡片的实战搭建指南,详细解析了独立后台系统的核心架构与自动化发卡流程。文章从零开始,手把手教你使用Node.js、Vue.js等技术栈构建包含后台管理、用户制卡中心与前端交互的完整系统,旨在帮助运营者实现合规引流,并掌握数据自主权与自动化运营能力。

weixin_29234423的博客 517

VC++下对匿名管道的编程实现

概述   管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。   匿名管道实施细则   匿名管道由CreatePipe()

Allan_Zeng的专栏 1633

Android息屏后台任务保活实战:从定时器失效到厂商白名单破解

本文深入探讨了Android应用在息屏后定时任务失效的根源,即系统为省电而触发的休眠机制。文章提供了从传统方案失效分析到实战破解的完整路径,核心在于引导用户将应用加入电池优化白名单并开启自启动权限,从而合法绕过限制。同时,结合WorkManager、AlarmManager等可靠定时方案,实现稳定的后台任务执行。

weixin_28475533的博客 422

孙鑫VC视频教程笔记之第十七课“进程间的通信”

  进程间通信的四种方式:Ø 剪贴板Ø 匿名管道Ø 命名管道Ø 邮槽 1.     剪贴板:剪贴板其实是系统管理的一个内存区域,当一个程序发生拷贝的时候,将是该内存区域得到填充,使用粘贴的时候是重该区域取出数据,然后显示的对应窗口上。 将指定内容赋值到剪贴板上:a.        打开剪贴板:OpenClipboard,注意:一旦打开了剪贴版,其它运用程

Roger Ge 的专栏 2168

力软敏捷开发框架源码7.0.6旗舰版 JNPF开发平台3.4.5 企业版 旗舰版

JNPF作为作为一款深受用户喜爱的低代码产品,凭借雄厚的科研技术力量、丰富的软件开发项目经验、严谨的项目开发流程和高质量的售后服务,已成功帮助千家企业完成数字化项目,建立了覆盖不同行业客户和不同发展阶段的软件产品服务体系。

huoooos0的博客 1839

C#上位机实战:借助NetToPLCSim与西门子S7-1200仿真通信全攻略

本文详细介绍了如何使用C#开发上位机程序,通过NetToPLCSim与西门子S7-1200进行仿真通信的全过程。从环境准备、PLC仿真环境搭建、网络配置到C#代码实现,提供了完整的实战指南和常见问题解决方案,帮助开发者快速掌握工业自动化通信技术。

weixin_30596343的博客 440

孙鑫VC学习笔记:第十七讲 用匿名管道实现进程间的通信

  用匿名管道实现进程间的通信: 匿名管道只能在本地主机上,父子进程之间完成通信: 步骤:1.新建一个项目Parent 2.增加“匿名管道”子菜单以及“创建管道”、“读取数据”与“写入数据”三个菜单项。3.在CParentView 中添加两个成员句柄:HANDLE m_hWrite;HANDLE m_hRead;4.为“创建管道”菜单项实现创建管道的

遐迩思的专栏 3616

YOLOv11模型压缩技术全面对比:剪枝、量化、蒸馏的原理与实战

YOLOv11模型压缩技术综述 模型压缩技术是解决计算资源受限环境下部署深度学习模型的关键。本文系统介绍了YOLOv11模型压缩的三种核心技术:剪枝、量化和蒸馏。剪枝技术通过移除冗余参数实现模型轻量化,包括结构化剪枝(通道/卷积核剪枝)和非结构化剪枝;量化技术通过降低数值精度(如FP32→INT8)减少存储和计算量;蒸馏技术则利用教师模型指导学生模型训练,在保持精度的同时减小模型规模。三种技术可单独或组合使用,在工业质检、智慧安防等边缘计算场景中发挥重要作用,使YOLOv11在保持80%精度的同时减少70%

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 577

孙鑫VC学习笔记:第十七讲 (一) 用剪贴板实现进程间的通信

孙鑫教学视频笔记(17)进程间通信---------------------------------------------------------------------------------进程间通信的四种方式剪贴板匿名管道命名管道邮槽 --------------------------------------------------------------

梦想---软件设计师 814

elevation mapping算法3之使用D435i相机离线或在线订阅点云和tf关系生成高程图

本文主要学习使用D435i相机发出的点云作为高程图的点云输入,如何离线输入点云生成高程图,进一步学习如何在线订阅点云生成高程图。

重点记录机器人和自动驾驶相关领域的技术,尤其是计算机视觉,视觉SLAM等,不仅有前言文献或必备算法的学习,也会有实际应用的点滴经验 3488

STM32声源定位:实现声源定位的嵌入式解决方案

通过以上代码,我们可以获取麦克风音频信号样本,并使用交叉相关法计算声源的位置。然而,我可以帮助您解答有关STM32声源定位的问题,提供相关的代码和指导。获取了麦克风音频信号后,我们可以使用信号处理算法来计算声源的位置。该算法通过计算不同麦克风之间的信号延迟来确定声源的方向。首先,我们需要获取每个麦克风的音频信号。声源定位是一项重要的技术,可以帮助我们确定声音的来源位置。在嵌入式系统中,使用STM32微控制器可以实现精确的声源定位。声源定位的基本原理是通过多个麦克风阵列接收到的声音信号来计算声源的位置。

UplKubernetes的博客 2581

孙鑫vc++ 17 进程间通信(2) 匿名管道

一、基础知识 1.匿名管道 匿名管道是一个未命名的、单向管道,通常用来在一个父进程和一个子进程之间传输数据。匿名管道只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信。 二、从代码进行分析 1.父进程 //管道的创建 void CParentView::OnPipeCreate() { // TODO: Add your command handler code here

2611

EDEM-FLUENT耦合报错几大原因总结(持续更新)

EDEM-FLUENT耦合报错几大原因总结(持续更新)

zheaa的博客 2760

c语言 邮槽通信,进程间通信的四种方式(孙鑫VC17集)

个人理解:(1)剪切板:是系统内部维护的一个内存区域(只适用本机中进程)。是系统提供的,所以所有的进程都可以访问(如记事本,WORD)等,复制是把数据放到剪切板中,粘贴则是从剪切板中取出数据。1.OpenClipboard()打开剪切板2.EmptyClipboard(),清空剪切板,并让发送数据端的对象能拥有剪切板的拥有权5.SetClipboardData(CF_TEXT,hand),在剪切板...

weixin_42526015的博客 337

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

孙鑫MFC笔记教程(17)--进程间通信1(匿名管道)

孙鑫VC学习笔记:第十七讲 (二) 用匿名管道实现进程间的通信 收藏 用匿名管道实现进程间的通信: 匿名管道只能在本地主机上,父子进程之间完成通信: 步骤:1.新建一个项目Parent 2.增加“匿名管道”子菜单以及“创建管道”、“读取数据”与“写入数据”三个菜单项。3.在CParentView 中添加两个成员句柄:HANDLE m_hWrite;HAN

liufei_learning--脚踏实地,戒骄戒躁! 3110

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

孙鑫VC学习笔记:第十七讲 用剪贴板实现进程间的通信

  孙鑫教学视频笔记(17)进程间通信---------------------------------------------------------------------------------进程间通信的四种方式剪贴板匿名管道命名管道邮槽 --------------------------------------------------------

遐迩思的专栏 2262

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

孙鑫VC视频教程笔记之第十七课“进程间的通信

进程间通信的四种方式:Ø 剪贴板Ø 匿名管道Ø 命名管道Ø 邮槽 1.     剪贴板:剪贴板其实是系统管理的一个内存区域,当一个程序发生拷贝的时候,将是该内存区域得到填充,使用粘贴的时候是重该区域取出数据,然后显示的对应窗

616

进程间通信的四种方式(孙鑫VC17集)

进程间通信的四种方式(孙鑫VC17集) (2011-01-17 15:32:45) 转载▼ 标签: 杂谈   个人理解: (1)剪切板:是系统内部维护的一个内存区域(只适用本机中进程)。是系统提供的,所以所有的进程都可以访问(如记事本,WORD)等,复制是把数据放到剪切板中,粘贴则是从剪切板中取出数据。   1.OpenCl

autumn20080101的专栏 446
上一篇: 孙鑫VC学习笔记:第十七讲 (一) 用剪贴板实现进程间的通信
下一篇: 孙鑫VC学习笔记:第十七讲 (三) 用命名管道实现进程间的通信
Savitch
博客等级 码龄16年 84粉丝 130原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值