网络编程——进程编程

Python网络编程中的多线程与多进程 Python 网络编程中的多线程与多进程是两种重要的并发编程模型。通过合理选择并发模型、优化资源利用和监控调试,可以实现高性能的网络应用程序。本文提供了丰富的代码和表格示例,帮助读者更好地理解和应用多线程与多进程编程技巧。在实际应用中,应根据任务类型选择合适的并发模型,并不断优化程序性能。 阅读详情

目的

(1)在理解进程的概念及其生命周期和状态转换过程的基础上,进行进程相关编程;
(2)在理解进程间通信的基本原理的基础上,编程实现进程间通信。

内容

(1)在Linux中利用fork()在父进程A中创建一个子进程B,再在子进程B中创建一个子进程C,在3个进程中都要编写适当的语句模拟进程的工作。
(2)创建子进程时将复制父进程的所有内容,此时的复制对象也包含套接字文件描述符。编写程序验证复制的文件描述符整数值是否与原文件描述符整数值相同。
(3)如果在未注册SIGINT信号的情况下输入Ctrl+C,将由操作系统默认的事件处理器终止程序。但如果直接注册Ctrl+C信号的处理器,则程序不会终止,而是调用程序员指定的事件处理器。编写注册处理函数的程序,完成如下功能:
“输入Ctrl+C时,询问是否确定退出程序,输入Y则终止程序。” 另外,编写程序使其每隔1秒输出简单字符串,并适用于上述时间处理器注册代码。
(4)利用fork()实现并发服务器,且让客户端的读写操作由两个进程分别处理。
(5)编写程序实现进程间通信,使2个进程相互交换3次字符串。当然,这2个进程应具有父子关系,各位可指定任意字符串。

实验代码及结果

(1)在Linux中利用fork()在父进程A中创建一个子进程B,再在子进程B中创建一个子进程C,在3个进程中都要编写适当的语句模拟进程的工作。

 //fork.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int gval=10;

int main(int argc, char *argv[])
{
	//父进程为进程A
	pid_t pid,pid1;
	int lval=20;
	gval++, lval+=5;
	//创建子进程B
	pid=fork();		
	if(pid==0)//如果是子进程B
	{
      	gval+=2, lval+=2;
		pid1=fork();//用子进程创建子进程C
		if(pid1==0)//如果是进程C
		{
			gval+=2, lval+=2;
		}
		else//如果是进程B
			gval-=2, lval-=2;
	}
	else			//如果是父进程A
		gval-=2, lval-=2;
	
	if(pid==0&&pid1!=0)
		printf("Child Proc: [%d, %d] \n", gval, lval);
	else if(pid1==0)
		printf("Child child Proc: [%d, %d] \n", gval, lval);
	else
		printf("Parent Proc: [%d, %d] \n", gval, lval);
	return 0;
}

测试结果:
在这里插入图片描述

(2)创建子进程时将复制父进程的所有内容,此时的复制对象也包含套接字文件描述符。编写程序验证复制的文件描述符整数值是否与原文件描述符整数值相同。

 //fockfdcheck.c
#include<stdio.h>
#include <unistd.h>
#include <sys/socket.h>

int main(int argc, char *argv[])
{
	pid_t pid;
	int sock=socket(PF_INET, SOCK_STREAM, 0);
	
	pid=fork();
    if(pid==0)
	{
		puts("Hi,I am a child process");
		//输出子进程中的sock值
		printf("Child sock fd: [%d] \n\n", sock);
	}		
	else
	{
		printf("Child Process ID:%d\n",pid);
		//输出父进程中的sock值
		printf("Parent sock fd: [%d] \n\n", sock);
	}
	//查看父进程与子进程的sock值是否一致
	close(sock);
	return 0;
}

测试结果:
在这里插入图片描述

(3)如果在未注册SIGINT信号的情况下输入Ctrl+C,将由操作系统默认的事件处理器终止程序。但如果直接注册Ctrl+C信号的处理器,则程序不会终止,而是调用程序员指定的事件处理器。编写注册处理函数的程序,完成如下功能: “输入Ctrl+C时,询问是否确定退出程序,输入Y则终止程序。” 另外,编写程序使其每隔1秒输出简单字符串,并适用于上述时间处理器注册代码。

//sigaction.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
//处理函数
void keycontrol(int sig)
{
	char c;
	if(sig==SIGINT)
	{
		fputs("Do you want to exit?[if so,put Y]:",stdout);
		scanf("%c",&c);
		if(c=='Y'||c=='y')
			exit(0);
	}
}

int main(int argc, char *argv[])
{
	int i;
	struct sigaction act;
	//注册信号
	act.sa_handler=keycontrol;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	//注册SIGINT信号处理器
	sigaction(SIGINT, &act, 0);


	for(i=0; i<100; i++)
	{
		puts("wait...");
		sleep(1);
	}
	return 0;
}

测试结果:
在这里插入图片描述

(4)利用fork()实现并发服务器,且让客户端的读写操作由两个进程分别处理。

//服务端
//mpserv.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define BUF_SIZE 30
void error_handling(char *message);
void read_childproc(int sig);

int main(int argc, char *argv[])
{
	int serv_sock, clnt_sock;
	struct sockaddr_in serv_adr, clnt_adr;
	
	pid_t pid;
	struct sigaction act;
	socklen_t adr_sz;
	int str_len, state;
	char buf[BUF_SIZE];
	if(argc!=2) {
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	}
    
    //注册信号
	act.sa_handler=read_childproc;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	state=sigaction(SIGCHLD, &act, 0);
	serv_sock=socket(PF_INET, SOCK_STREAM, 0);
	memset(&serv_adr, 0, sizeof(serv_adr));
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_adr.sin_port=htons(atoi(argv[1]));
	
	if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr))==-1)
		error_handling("bind() error");
	if(listen(serv_sock, 5)==-1)
		error_handling("listen() error");
	
	while(1)
	{
		adr_sz=sizeof(clnt_adr);
		clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);
		if(clnt_sock==-1)
			continue;
		else
			puts("new client connected...");
		pid=fork();
		if(pid==-1)
		{
			close(clnt_sock);
			continue;
		}
		if(pid==0)//如果是子进程,负责接收一个客户端的信息,如果是父进程,继续监听
		{
			close(serv_sock);
			while((str_len=read(clnt_sock, buf, BUF_SIZE))!=0)
				write(clnt_sock, buf, str_len);
			
			close(clnt_sock);
			puts("client disconnected...");
			return 0;
		}
		else
			close(clnt_sock);
	}
	close(serv_sock);
	return 0;
}
//信号产生时的处理事件
void read_childproc(int sig)
{
	pid_t pid;
	int status;
	pid=waitpid(-1, &status, WNOHANG);
	printf("removed proc id: %d \n", pid);
}
void error_handling(char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}
//客户端
//mpclient.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define BUF_SIZE 30
void error_handling(char *message);
void read_routine(int sock, char *buf);
void write_routine(int sock, char *buf);

int main(int argc, char *argv[])
{
	int sock;
	pid_t pid;
	char buf[BUF_SIZE];
	struct sockaddr_in serv_adr;
	if(argc!=3) {
		printf("Usage : %s <IP> <port>\n", argv[0]);
		exit(1);
	}
	
	sock=socket(PF_INET, SOCK_STREAM, 0);  
	memset(&serv_adr, 0, sizeof(serv_adr));
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=inet_addr(argv[1]);
	serv_adr.sin_port=htons(atoi(argv[2]));
	
	if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
		error_handling("connect() error!");

	pid=fork();
	if(pid==0)
		//如果是子进程,负责写
		write_routine(sock, buf);
	else 
		//否则是父进程,负责读
		read_routine(sock, buf);

	close(sock);
	return 0;
}
//读函数
void read_routine(int sock, char *buf)
{
	while(1)
	{
		int str_len=read(sock, buf, BUF_SIZE);
		if(str_len==0)
			return;
		buf[str_len]=0;
		printf("Message from server: %s", buf);
	}
}
//写函数
void write_routine(int sock, char *buf)
{
	while(1)
	{
		fgets(buf, BUF_SIZE, stdin);
		if(!strcmp(buf,"q\n") || !strcmp(buf,"Q\n"))
		{	
			shutdown(sock, SHUT_WR);
			return;
		}
		write(sock, buf, strlen(buf));
	}
}
void error_handling(char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

测试结果:
在这里插入图片描述
在这里插入图片描述

(5)编写程序实现进程间通信,使2个进程相互交换3次字符串。当然,这2个进程应具有父子关系,各位可指定任意字符串。

//pidmessage.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUF_SIZE 30

int main(int argc, char *argv[])
{
	int fds1[2], fds2[2];
	char *str1[]={"hello","nice to meet you","good bye"};//子进程需要发送的字符串
	char *str2[]={"hello","nice to meet you too","bye"};//父进程需要发送的字符串
	char buf[BUF_SIZE];
	pid_t pid;
	int i;
	
	pipe(fds1), pipe(fds2);//建立管道
	pid=fork();
	
	//利用管道进行进程间的通信
	if(pid==0)
	{
		for(i=0; i<3; i++)
		{
			write(fds1[1], str1[i], strlen(str1[i])+1);
			read(fds2[0], buf, BUF_SIZE);
			printf("Child proc output: %s \n",  buf);
		}
	}
	else
	{
		for(i=0; i<3; i++)
		{
			read(fds1[0], buf, BUF_SIZE);
			printf("Parent proc output: %s \n", buf);
			write(fds2[1], str2[i], strlen(str2[i])+1);
			sleep(2);
		}
	}
	return 0;
}

测试结果:
在这里插入图片描述
对于网络编程中,创建多个进程能够让服务端实现与多个客户端通信,从而实现了服务端的并发性,提高了通信效率。
一开始对于fork函数的理解有点误区,fork函数是通过复制正在运行、调用fork函数的进程来工作的,复制相同的内存空间,通过返回值加以区分。同时需要特别注意,父子进程拥有完全独立的内存结构。

掌握网络编程与进程管理的秘籍 本文深入探讨了网络编程和进程管理中的关键函数,包括获取网络信息、进程控制和文件处理等。通过细致的函数语法和描述,为读者提供了丰富的编程工具和技巧,旨在提高开发者的编程能力和效率。 阅读详情

相关推荐

进程编程总结

自己总结的进程的编程技巧,还有进程的一些性质,进程退出,适合初学者。

Python多进程编程

一 多进程编程Python实现多进程的方式有两种:一种方法是os模块中的fork方法,另一种是使用multiprocessing模块。前者仅适用于LINUX/UNIX操作系统,对Windows不支持,后者则是跨平台的实现方式。第一种方式:使用os模块中的fork方式实现多进程第二种方式:multiprocessing由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。

m0_59485658的博客 2013

HPC软件使用之ANSYS Fluent

本文介绍了如何在超级计算机上使用ANSYS Fluent进行科学计算和工程仿真。文章首先对Fluent软件进行了简要介绍,强调了其在计算流体力学领域的广泛应用和强大功能。接着,详细说明了如何编写jou脚本文件和slurm脚本文件,以控制Fluent的计算流程和作业提交。文章还提供了作业提交和查看的具体命令,并通过一个鼓风机仿真的案例演示了从网格模型准备、脚本编写、作业提交到结果查看的完整流程。最后,展示了使用Fluent进行结果可视化的方法。

欢迎各位大佬光临“寒舍”!请多多指点,共同进步! 2212

(TCP IP网络编程)实验四 进程编程

一.实验目的 (1) 在理解进程的概念及其生命周期和状态转换过程的基础上,进行进程相关编程; (2) 在理解进程间通信的基本原理的基础上,编程实现进程间通信。 二.实验内容 (1) 在Linux中利用fork()在父进程A中创建一个子进程B,再在子进程A中创建一个子进程C,在3个进程中都要编写适当的语句模拟进程的工作。 (2) 创建子进程时将复制父进程的所有内容,此时的复制对象也包含套接字文件描述符。编写程序验证复制的文件描述符整数值是否与原文件描述符整数值相同。 (3) 如果在未注册SIGINT信号

weixin_44209522的博客 1880

innovus中path group 的策略和应用(上)

在所有的后端工具里边,有三个重要的引擎:auto-place,CTS,auto-route三个。这里边的auto-place是决断了整个设计时序的基点。。当然,就算是到了CTS/route阶段后,也可以继续利用auto-place数据优化的功能,在数据库上做数据路径增量优化(optDesign -increment)。可以说,数据路径的优化手段,实际上是贯穿在整个后端流程上的。。看看这其中的奥妙和有趣的事情。ICer GO!

i_chip_backend的博客 4218

如何入门强化学习

很多同学在入门强化学习的时候都会遇到困难,那我这里就简单介绍一下应该如何入门强化学习,并以开源代码为例详解强化学习实战。

seeksister的博客 3304

Linux系统编程之进程

进程把两字分开来理解,“进”就是进行,“程”就是程序。所以,进程指的就是正在运行(进行)的程序。守护进程运行在后台,不跟任何控制终端关联。

m0_75183905的博客 797

【YOLOv11工业级实战】22. YOLOv11动态蛇形卷积破解弯曲裂纹检测难题(附2小时部署代码)

摘要:本文聚焦工业场景中弯曲裂纹检测的核心痛点,针对风电叶片、织物纱线等曲线缺陷传统检测漏检率高的问题,提出基于动态蛇形卷积(DSC)的YOLOv11优化方案。因企业数据保密,采用AITEX织物缺陷库(含曲线纱线断裂标签)结合Blender物理仿真生成2000张弯曲裂纹数据,实现从数据准备到部署的全流程实操。通过将DSC模块插入YOLOv11 Neck层,弯曲裂纹召回率从68.1%提升至89.4%,mAP@0.5达83.7%,推理速度3.1ms(2080Ti)。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1153

网络编程:多进程和多线程编程

初始化时,shm_lpid、shm_nattach、shm_atime、shm_dtime 设置为 0,shm_ctime 设置为当前时间;创建共享内存,所有字节都被初始化为 0,与之关联的内核数据结构为 shmid_ds 被创建和初始化;作用是创建并初始化它,会将 sem_otime 设为 0,sem_ctime 设为当前系统时间;num_sems 指定信号量集中信号量的数目;操作,会更新进程的 semadj 变量,,来跟踪进程对信号量的修改情况;创建一个新的信号量集,或者获取一个已经存在的信号量集;

weixin_44835655的博客 490

ESP32-S3驱动OV3660摄像头原理图设计,已量产

本文重点拆四条主线:多来源输入电源如何收敛到 3V3,摄像头三路供电如何拆分,ESP32-S3 如何接住 DVP 数据流与外部存储,以及音频/补光/传感外围怎样挂到主控边上。至于最终图像帧率、算法策略和软件时序,当前原理图未体现。

不脱发的程序猿 983

安装Codex时出现无法下载此应用和Microsoft Store初始化失败的解决方案

本文主要介绍了安装Codex时出现无法下载此应用和Microsoft Store初始化失败的解决方案,希望能对使用codex的同学们有所帮助。 文章目录 1. 问题描述 2. Windows 解决方案 3. Mac解决方案

weixin_43178406的博客 7万+

进程以及多线程编程

一个程序运行起来,在操作系统中,就会出现一个对应的进程。也就是说,进程就是一个跑起来的应用程序我们可以在任务管理器中就把当前运行的所有进程都列出来除了自己运行的程序是进程外,还有一些系统自带的程序也是进程右边显示的那些CPU,内存,磁盘…就是当前进程占用了多少对应的系统资源。要想让一个程序运行,就必须给这个进程分配系统资源,包括不限于CPU,内存,硬盘,网络带宽,显卡…所以在操作系统内部,进程又是操作系统进行资源分配的基本单位。而进程多了就需要进行管理,做法则是先描述,再组织。

2302_77179144的博客 768

PCB层叠结构与阻抗计算

1.Core 和 PP PCB两个重要组成部分:Core 和 Prepreg(半固态片,简称PP)。 如下图所示, Core 的两个表面都铺有铜箔,可作为信号层、电源层、地层等导电层,Core的上下表面之间填充的是固态材料; PP的表面不铺铜,在PCB中起填充作用,其材质是半固体的树脂材料,因此比Core略软一些。 在制作多层板时,需配合使用Core和PP,一般在两个Core 之间应选PP作为填...

sinat_15677011的博客 1万+

Python进阶中网络编程与进程线程

进程与线程概念与区别

wwwwwjjnsnns的博客 671

CDD数据库文件制作(二)——服务配置(0x27)

主要根据诊断调查表,针对0x27服务在CDD中的每一步配置给出详细介绍 1.会话切换配置 1.1.根据诊断调查表进行信息提取 1.2.子功能添加 1.2.1.Level1安全等级1创建 1.2.2.Level3安全等级3创建 1.2.3.安全等级名字查看与修改 1.3.会话切换信息提取(应用程序下) 1.4.会话转换配置(应用程序下) 1.5.会话切换信息提取(引导程序下) 1.6.会话转换配置(引导程序下) 2.安全等级配置信息提取 2.1.安全访问配置(level1) 2.2.安全访问配置(level2

LOVE135149的博客 2930

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Python 网络编程、进程

网编三要素IP地址:概念:计算机的唯一标识;标识网络设备的一个地址。通过IP地址找到网络中唯一一台设备表现形式:IPv4:点分十进制(4组8位,用 . 分隔)IPv6:冒号分十六进制(8组16位,用 : 分隔)支持压缩( :: 代替连续的0)查看IP地址:cmd -> ipconfig检查网络:cmd -> ping +网址端口:标识进程的逻辑地址;每一个运行的程序都有一个端口,想要给对应的程序发送信息,找到对应的端口号传输数据的通道;

huangch001002的博客 672

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Linux网络编程——守护进程

在我们上一篇TCP网络通信文章中,我们使用了守护线程,但是当时没有做过多的了解,下面再本文中,我们再做详细介绍。

学习日记 1332

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

进程编程、TCP、UDP网络编程及工作原理详解

第一部分:进程编程基础及TCP网络编程 利用Linux环境中的fork函数来进行进程编程,以产生子进程。(参考教材8.2.2节,理解fork函数产生子进程在内存中是如何工作的,即fork函数的工作原理。需要在实训报告中详细阐述。) fork函数的工作原理: fork()系统调用通过复制一个现有进程来创建一个全新的进程。进程被存放在一个叫做任务队列的双向循环链表当中,链表当中的每一项都是类型为task_struct称为进程描述符的结构,也就是我们写过的进程PCB.内核通过一个位置的进程标识值或PID来标识

daidaidaiqqq的博客 608

【Linux网络编程】守护进程

前后台进程与守护进程大学习

2303_80828380的博客 874

Python Day25 进程与网络编程

本文总结了Python多进程编程的核心知识点,包括:1)进程创建方式(fork、Process类、继承重写run方法、进程池);2)多进程售票系统实现;3)死锁概念及解决方案;4)网络协议基础(TCP/UDP特性对比);5)Socket编程实现TCP服务器/客户端;6)完整聊天室案例(包含服务器和客户端实现)。重点演示了多进程数据隔离特性、进程间通信(Queue、Lock)、以及基于Socket和线程的实时聊天系统开发,涵盖从进程创建到网络通信的全流程实践。

ihghhfffv的博客 767

网络编程(多进程、多线程)

linux下多进程网络通信浅述

vx_ahhhhyx319的博客 404

【Python】进阶 - 网络编程(TCP开发基础、进程和线程)

本文摘要: Python网络编程与并发编程指南,涵盖TCP/IP协议栈、进程和线程的核心概念。主要内容包括:1)网络编程三要素(IP地址、端口号、协议)及socket类使用;2)TCP客户端/服务器开发流程与代码示例;3)进程与线程的对比分析,重点介绍multiprocessing和threading模块的使用;4) 进程间内存隔离特性与线程共享全局变量的区别;5) 守护进程/线程的设置方法。文章通过代码示例详细演示了网络通信和并发编程的实现方式,并分析了不同场景下的适用方案(CPU密集型推荐多进程,IO密

weixin_52613525的博客 999

python网络编程&线程与进程

day4 上六天休一天,昨天回家了,今天是课程的第四天,讲了网络编程以及线程与进程,稍微偏概念了一些,有点枯燥,老师线程没讲完,明天剩下的明天会再编辑。

aliedudu的博客 896

人工智能学习之python网络编程与多任务和进程

给客户端发送数据 b是将数据转化为2进制的 a.send(b"".encode('UTF-8')) # 发出指令 字符串前要带 b'里面是英文' 或者"里面是中文".encode('UTF-8')接受客户端的信息并打印 1024为单次会话上线 data = a.recv(1024).decode('UTF-8')ipv6 8字节16进制。连接服务器端,指定的服务器端的ip 接口号 c.connect((ip,端口))

qq_54220583的博客 1165

网络编程与进程

网络编程与进程

cyq1123的博客 176

Linux系统编程实战指南:从进程管理到网络编程

本文基于实际项目经验,深入浅出地介绍Linux系统编程的核心概念和实践技巧。涵盖进程管理、信号处理、进程间通信、网络编程等关键主题。

2301_80436820的博客 879
上一篇: 网络编程——广播与多播编程
下一篇: 网络编程——I/O复用模型编程
DiliLearngent
博客等级 码龄7年 977粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值