【Linux】网络篇二--TCP编程_linux之网络编程(tcp)头歌

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注运维)
img

正文

返回值:成功实际接收的字节数,失败-1, 并设置errno

  • buffer : 发送缓冲区首地址
  • length : 发送的字节数
  • flags : 接收方式(通常为0)
    • MSG_DONTWAIT: Enables nonblocking operation; 非阻塞版本
    • MSG_OOB:用于发送TCP类型的带外数据(out-of-band)
    • MSG_PEEK
      接收消息的开头,但不删除该消息数据。 因此,随后的接收将
      返回相同的数据

10、read()/write()
ssize\_t read(int fd, void \*buf, size\_t count);
ssize\_t write(int fd, const void \*buf, size\_t count);

  • read()和write()经常会代替recv()和send()
  • 通常情况下,看程序员的偏好
    使用read()/write()和recv()/send()时最好统一

11、套接字的关闭
int close(int sockfd); //关闭双向通讯
int shutdown(int sockfd, int howto);

  • TCP连接双向的(是可读写的),当我们使用close时,会把读写通道都关闭,有时侯我们希望只关闭一个方向,这个时候我们可以使用shutdown
  • 针对不同的howto,系统回采取不同的关闭方式。
    • howto = 0
      关闭读通道,但是可以继续往套接字写数据。
    • howto = 1
      和上面相反,关闭写通道。只能从套接字读取数据。
    • howto = 2
      关闭读写通道,和close()一样

示例

客机向服务器写数据,服务器读数据并打印

net.h-包含的头文件以及宏定义

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
 > File Name: net.h
 > Author: xiuchengzhen
 > CSDN: xiuchengzhen.blog.csdn.net
 > Created Time: Tue 29 Mar 2022 05:45:13 AM PDT
 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/

#ifndef NET\_H
#define NET\_H

#include<stdio.h> 
#include<stdlib.h> 
#include <string.h>
#include <sys/socket.h> 
#include<unistd.h> 
#include <arpa/inet.h> 
#include <sys/types.h> 
#include<errno.h>

#define SER\_PORT 5001 //端口号
#define SER\_ADDR "192.168.125.128" //ip地址
#define BUFSIZE 15 //发送数据的大小(字节)
#define USER\_QUIT "quit" (退出命令)

#endif

服务器sever.c:

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
 > File Name: sever.c
 > Author: xiuchengzhen
 > CSDN: xiuchengzhen.blog.csdn.net
 > Created Time: Tue 29 Mar 2022 01:41:36 AM PDT
 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#include "net.h"

int main(int argc, const char \*argv[])
{
	/\*\*\*\*\*\*\*\*socket文件创建\*\*\*\*\*\*\*\*\*\*\*/
	int fd = socket( AF_INET, SOCK_STREAM, 0);
	if(fd < 0)
	{
		perror("socket");
		exit(-1);
	}

	/\*\*\*\*\*\*\*bind设置\*\*\*\*\*\*\*/
	struct sockaddr\_in sin;
	memset(&sin, 0, sizeof(sin));  //清零操作

	sin.sin_family = AF_INET; //地址族
	sin.sin_port = htons(SER_PORT);
#if 0
	sin.sin_addr = inet\_addr(SER_ADDR);
#else
	if(inet\_pton(AF_INET, SER_ADDR, (void \*)&sin.sin_addr) == 0)
	{
		perror("inet\_pton:");
		exit(-1);
	}
#endif
	if(bind(fd, (struct sockaddr \*)&sin,sizeof(sin)) < 0)
	{
		perror("bind:");
		exit(-1);
	}

	/\*\*\*\*\*\*\*\*listen\*\*\*\*\*\*\*\*\*/
	if(listen(fd, 5) < 0)
	{
		perror("listen:");
		exit(-1);
	}

	/\*\*\*\*\*\*\*accept阻塞接收\*\*\*\*\*\*\*\*\*/
	int newfd;
	if((newfd = accept(fd, NULL, NULL)) < 0)
	{
		perror("accept:");
		exit(-1);
	}

	/\*\*\*\*\*\*read\*\*\*\*\*\*\*/
	char buf[BUFSIZE];
	int ret = -1;
	while(1)
	{
		bzero((void \*)buf, BUFSIZE);  //清零
		do
		{
			ret = read(newfd, (void \*)buf, BUFSIZE-1);
		}while(ret < 0 && EINTR == errno); //没读到就一直读
		if(ret < 0) //读错误
		{
			perror("read");
			exit(-1);
		}
		if(ret == 0) //连接断开
		{
			printf("client break link!\n");
			break;
		}

		printf("re:%s\n", buf);
		if(strncasecmp(buf, USER_QUIT, strlen(USER_QUIT)) == 0) 
		{
			printf("client choice break link!\n");
			break;
		}
	}

	/\*\*\*\*\*\*\*\*\*关闭网络\*\*\*\*\*\*\*\*\*\*\*/
	close(newfd);
	close(fd);

	return 0;
}

客机client.c:

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
 > File Name: client.c
 > Author: xiuchengzhen
 > CSDN: xiuchengzhen.blog.csdn.net
 > Created Time: Tue 29 Mar 2022 05:43:55 AM PDT
 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/

#include "net.h"

int main(int argc, const char \*argv[])
{
	/\*\*\*\*\*\*\*\*socket文件创建\*\*\*\*\*\*\*\*\*\*\*/
	int fd = socket( AF_INET, SOCK_STREAM, 0);
	if(fd < 0)
	{
		perror("socket");
		exit(-1);
	}

	/\*\*\*\*\*\*\*connect设置\*\*\*\*\*\*\*/
	struct sockaddr\_in sin;
	memset(&sin, 0, sizeof(sin));  //清零操作

	sin.sin_family = AF_INET;
	sin.sin_port = htons(SER_PORT);
#if 0
	sin.sin_addr = inet\_addr(SER_ADDR);
#else
	if(inet\_pton(AF_INET, SER_ADDR, (void \*)&sin.sin_addr) == 0)
	{
		perror("inet\_pton:");
		exit(-1);
	}
#endif
	if(connect(fd, (struct sockaddr \*)&sin,sizeof(sin)) < 0)
	{
		perror("connect:");
		exit(-1);
	}
	
	printf("client connect success!\n");
	char buf[BUFSIZE] = {0};
	int ret = -1;
	while(1)
	{
		bzero(buf, 0);
		if(fgets(buf, BUFSIZE-1, stdin) == 0)
		{
			continue;
		}

		do
		{
			ret = write(fd, buf, strlen(buf));
		}while(ret < 0 && EINTR == errno);
	
		if (!strncasecmp (buf, USER_QUIT, strlen (USER_QUIT))) 
		{
			printf ("Client is exiting!\n");
			break;
		}
	}
	return 0;
}

运行结果:
在这里插入图片描述


二、并发编程

在这里插入图片描述

主要是应对当多个客机对服务器进行连接的情况

  • 当一个客机与服务器连接时,服务器创建一个线程或一个子进程为客机单独服务,主函数继续等待新的客机连接

1、多线程并发

实现过程在上面的例子上稍微改进
头文件net.h:

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
 > File Name: net.h
 > Author: xiuchengzhen
 > CSDN: xiuchengzhen.blog.csdn.net
 > Created Time: Tue 29 Mar 2022 05:45:13 AM PDT
 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/

#ifndef NET\_H
#define NET\_H

#include<stdio.h> 
#include<stdlib.h> 
#include <string.h>
#include <sys/socket.h> 
#include<unistd.h> 
#include <arpa/inet.h> 
#include <sys/types.h> 
#include<errno.h>
#include <netinet/in.h>
#include<pthread.h>

#define SER\_PORT 5001
#define SER\_ADDR "192.168.125.128"
#define BUFSIZE 15 
#define USER\_QUIT "quit"
#define BACK\_LOG 5

#endif

服务器sever.c:

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
 > File Name: sever.c
 > Author: xiuchengzhen
 > CSDN: xiuchengzhen.blog.csdn.net
 > Created Time: Tue 29 Mar 2022 01:41:36 AM PDT
 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#include "net.h"

void \*client\_hander(void \*arg);

int main(int argc, const char \*argv[])
{
	int i = 0;
	/\*\*\*\*\*\*\*\*socket文件创建\*\*\*\*\*\*\*\*\*\*\*/
	int fd = socket( AF_INET, SOCK_STREAM, 0);
	if(fd < 0)
	{
		perror("socket");
		exit(-1);
	}

	/\*\*\*\*\*\*\*bind设置\*\*\*\*\*\*\*/
	struct sockaddr\_in sin;
	memset(&sin, 0, sizeof(sin));  //清零操作

	sin.sin_family = AF_INET;
	sin.sin_port = htons(SER_PORT);
	/\*\*\*\*\*\*\*\*\*\*\*优化1\*\*\*\*\*\*\*\*\*\*/
#if 1
	sin.sin_addr.s_addr = htonl(INADDR_ANY);   //当系统IP地址发生变化时,这里的地址也会随着变化
#else
	if(inet\_pton(AF_INET, SER_ADDR, (void \*)&sin.sin_addr) == 0)
	{
		perror("inet\_pton:");
		exit(-1);
	}
#endif
	if(bind(fd, (struct sockaddr \*)&sin,sizeof(sin)) < 0)
	{
		perror("bind:");
		exit(-1);
	}

	/\*\*\*\*\*\*\*\*listen\*\*\*\*\*\*\*\*/
	if(listen(fd, BACK_LOG) < 0)  //设置为服务器模式,与最大接收数
	{
		perror("listen:");
		exit(-1);
	}

	/\*\*\*\*\*\*\*\*\*多线程优化\*\*\*\*\*\*\*\*\*/
	/\*\*\*\*\*\*\*accept阻塞接收\*\*\*\*\*\*\*\*\*/
	while(1)
	{
#if 0
		int newfd;
		if((newfd = accept(fd, NULL, NULL)) < 0)
		{
			perror("accept:");
			exit(-1);
		}
#else
		int newfd[BACK_LOG];
		struct sockaddr\_in cin;
		char client_ip[16] = {0};
		socklen\_t cin_len = (socklen\_t)sizeof(cin);

		memset(&cin, 0, sizeof(cin));

		if((newfd[i] = accept(fd, (struct sockaddr \*)&cin, &cin_len)) < 0)  //阻塞接收
		{
			perror("accept:");
			exit(-1);
		}

		if(inet\_ntop(AF_INET, (void \*)&cin.sin_addr, client_ip, sizeof(cin)) == NULL)
		{
			perror("inet\_ntop:");
			exit(-1);
		}
		printf("client Port:%d,IP:%s\n",ntohs(cin.sin_port), client_ip);
#endif

		pthread\_t tid;
		if(pthread\_create(&tid, NULL, client_hander, (void \*)&newfd[i]) != 0)
		{
			printf("tid create error!\n");
			exit(-1);
		}
		i++;
	}
	close(fd);

	return 0;
}

void \*client\_hander(void \*newfd)
{
	pthread\_detach(pthread\_self());  //设置线程分离属性,线程结束时自动回收
	/\*\*\*\*\*\*read\*\*\*\*\*\*\*/
	char buf[BUFSIZE];
	int ret = -1;
	while(1)
	{
		bzero((void \*)buf, BUFSIZE);
		do
		{
			ret = read(\*(int \*)newfd, (void \*)buf, BUFSIZE-1);
		}while(ret < 0 && EINTR == errno);
		if(ret < 0)
		{
			perror("read");
			exit(-1);
		}
		if(ret == 0)
		{
			printf("fd:%d client break link!\n", \*(int \*)newfd);
			break;
		}

		printf("fd:%d read:%s\n", \*(int \*)newfd, buf);
		if(strncasecmp(buf, USER_QUIT, strlen(USER_QUIT)) == 0)
		{
			printf("fd:%d client choice break link!\n", \*(int \*)newfd);
			break;
		}
	}

	/\*\*\*\*\*\*\*\*\*关闭网络\*\*\*\*\*\*\*\*\*\*\*/
	close(\*(int \*)newfd);
	return NULL;
}

客机client.c:

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
 > File Name: client.c
 > Author: xiuchengzhen
 > CSDN: xiuchengzhen.blog.csdn.net
 > Created Time: Tue 29 Mar 2022 05:43:55 AM PDT
 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/

#include "net.h"

int main(int argc, const char \*argv[])
{
	if(argc < 2)
	{
		printf("Please enter the port and address at run time!\n");  // ./运行文件 端口号 IP
		printf("For example:\n ./ file port IP\n");
		exit(-1);
	}
	/\*\*\*\*\*\*\*\*socket文件创建\*\*\*\*\*\*\*\*\*\*\*/
	int fd = socket( AF_INET, SOCK_STREAM, 0);
	if(fd < 0)
	{
		perror("socket");
		exit(-1);
	}

	/\*\*\*\*\*\*\*connect设置\*\*\*\*\*\*\*/
	struct sockaddr\_in sin;
	int port = atoi(argv[1]);
	if(port < 5000)
	{
		printf("The port number must be smaller than 5000\n");
		exit(-1);
	}
	memset(&sin, 0, sizeof(sin));  //清零操作

	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
#if 0
	sin.sin_addr = inet\_addr(argv[2]);
#else
	if(inet\_pton(AF_INET, argv[2], (void \*)&sin.sin_addr) == 0)
	{
		perror("inet\_pton:");
		exit(-1);
	}
#endif

	if(connect(fd, (struct sockaddr \*)&sin,sizeof(sin)) < 0)
	{
		perror("connect:");
		exit(-1);
	}
	
	printf("client connect success!\n");
	char buf[BUFSIZE] = {0};
	int ret = -1;
	while(1)
	{
		bzero(buf, 0);
		if(fgets(buf, BUFSIZE-1, stdin) == 0)
		{
			continue;
		}

		do
		{
			ret = write(fd, buf, strlen(buf));
		}while(ret < 0 && EINTR == errno);
	
		if (!strncasecmp (buf, USER_QUIT, strlen (USER_QUIT))) 
		{
			printf ("Client is exiting!\n");
			break;
		}
	}
	return 0;
}

运行结果:
在这里插入图片描述


2、多进程并发

只需在服务器上改动,其他不变:

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
 > File Name: sever\_process.c
 > Author: xiuchengzhen
 > CSDN: xiuchengzhen.blog.csdn.net
 > Created Time: Tue 29 Mar 2022 01:41:36 AM PDT
 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#include "net.h"

void process\_hander(int log);
void client\_hander(int arg);

int main(int argc, const char \*argv[])
{
	signal(SIGCHLD, process_hander);
	/\*\*\*\*\*\*\*\*socket文件创建\*\*\*\*\*\*\*\*\*\*\*/
	int fd = socket( AF_INET, SOCK_STREAM, 0);
	if(fd < 0)
	{
		perror("socket");
		exit(-1);
	}

	/\*\*\*\*\*\*\*bind设置\*\*\*\*\*\*\*/
	struct sockaddr\_in sin;
	memset(&sin, 0, sizeof(sin));  //清零操作

	sin.sin_family = AF_INET;
	sin.sin_port = htons(SER_PORT);
	/\*\*\*\*\*\*\*\*\*\*\*优化1\*\*\*\*\*\*\*\*\*\*/
#if 1
	sin.sin_addr.s_addr = htonl(INADDR_ANY);   //当系统IP地址发生变化时,这里的地址也会随着变化
#else
	if(inet\_pton(AF_INET, SER_ADDR, (void \*)&sin.sin_addr) == 0)
	{
		perror("inet\_pton:");
		exit(-1);
	}
#endif
	if(bind(fd, (struct sockaddr \*)&sin,sizeof(sin)) < 0)
	{
		perror("bind:");
		exit(-1);
	}

	/\*\*\*\*\*\*\*\*listen\*\*\*\*\*\*\*\*/
	if(listen(fd, BACK_LOG) < 0)  //设置为服务器模式,与最大接收数
	{
		perror("listen:");
		exit(-1);
	}

	/\*\*\*\*\*\*\*\*\*多进程优化\*\*\*\*\*\*\*\*\*/
	/\*\*\*\*\*\*\*accept阻塞接收\*\*\*\*\*\*\*\*\*/
	while(1)
	{
#if 0
		int newfd;
		if((newfd = accept(fd, NULL, NULL)) < 0)
		{
			perror("accept:");
			exit(-1);
		}
#else
		int newfd;
		struct sockaddr\_in cin;
		char client_ip[16] = {0};
		socklen\_t cin_len = (socklen\_t)sizeof(cin);

		memset(&cin, 0, sizeof(cin));

		if((newfd = accept(fd, (struct sockaddr \*)&cin, &cin_len)) < 0)  //阻塞接收
		{
			perror("accept:");


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)**
![img](https://img-blog.csdnimg.cn/img_convert/2b03b4a99ce4b10c551157489396f343.jpeg)

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
\*\*\*\*\*\*accept阻塞接收\*\*\*\*\*\*\*\*\*/
	while(1)
	{
#if 0
		int newfd;
		if((newfd = accept(fd, NULL, NULL)) < 0)
		{
			perror("accept:");
			exit(-1);
		}
#else
		int newfd;
		struct sockaddr\_in cin;
		char client_ip[16] = {0};
		socklen\_t cin_len = (socklen\_t)sizeof(cin);

		memset(&cin, 0, sizeof(cin));

		if((newfd = accept(fd, (struct sockaddr \*)&cin, &cin_len)) < 0)  //阻塞接收
		{
			perror("accept:");


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)**
[外链图片转存中...(img-JNPPpdFy-1713460293532)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值